4101 lines · cpp
1//===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/RISCVAsmBackend.h"10#include "MCTargetDesc/RISCVBaseInfo.h"11#include "MCTargetDesc/RISCVInstPrinter.h"12#include "MCTargetDesc/RISCVMCAsmInfo.h"13#include "MCTargetDesc/RISCVMCTargetDesc.h"14#include "MCTargetDesc/RISCVMatInt.h"15#include "MCTargetDesc/RISCVTargetStreamer.h"16#include "TargetInfo/RISCVTargetInfo.h"17#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/SmallBitVector.h"19#include "llvm/ADT/SmallVector.h"20#include "llvm/ADT/Statistic.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/MC/MCAssembler.h"23#include "llvm/MC/MCContext.h"24#include "llvm/MC/MCExpr.h"25#include "llvm/MC/MCInst.h"26#include "llvm/MC/MCInstBuilder.h"27#include "llvm/MC/MCInstrInfo.h"28#include "llvm/MC/MCObjectFileInfo.h"29#include "llvm/MC/MCParser/AsmLexer.h"30#include "llvm/MC/MCParser/MCParsedAsmOperand.h"31#include "llvm/MC/MCParser/MCTargetAsmParser.h"32#include "llvm/MC/MCRegisterInfo.h"33#include "llvm/MC/MCStreamer.h"34#include "llvm/MC/MCSubtargetInfo.h"35#include "llvm/MC/MCValue.h"36#include "llvm/MC/TargetRegistry.h"37#include "llvm/Support/Casting.h"38#include "llvm/Support/CommandLine.h"39#include "llvm/Support/Compiler.h"40#include "llvm/Support/MathExtras.h"41#include "llvm/Support/RISCVAttributes.h"42#include "llvm/TargetParser/RISCVISAInfo.h"43 44#include <limits>45#include <optional>46 47using namespace llvm;48 49#define DEBUG_TYPE "riscv-asm-parser"50 51STATISTIC(RISCVNumInstrsCompressed,52 "Number of RISC-V Compressed instructions emitted");53 54static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",55 cl::init(false));56 57namespace llvm {58extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];59} // namespace llvm60 61namespace {62struct RISCVOperand;63 64struct ParserOptionsSet {65 bool IsPicEnabled;66};67 68class RISCVAsmParser : public MCTargetAsmParser {69 // This tracks the parsing of the 4 optional operands that make up the vtype70 // portion of vset(i)vli instructions which are separated by commas.71 enum class VTypeState {72 SeenNothingYet,73 SeenSew,74 SeenLmul,75 SeenTailPolicy,76 SeenMaskPolicy,77 };78 79 SmallVector<FeatureBitset, 4> FeatureBitStack;80 81 SmallVector<ParserOptionsSet, 4> ParserOptionsStack;82 ParserOptionsSet ParserOptions;83 84 SMLoc getLoc() const { return getParser().getTok().getLoc(); }85 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }86 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); }87 bool enableExperimentalExtension() const {88 return getSTI().hasFeature(RISCV::Experimental);89 }90 91 RISCVTargetStreamer &getTargetStreamer() {92 assert(getParser().getStreamer().getTargetStreamer() &&93 "do not have a target streamer");94 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();95 return static_cast<RISCVTargetStreamer &>(TS);96 }97 98 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,99 unsigned Kind) override;100 101 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,102 int64_t Lower, int64_t Upper,103 const Twine &Msg);104 bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,105 const Twine &Msg);106 107 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,108 OperandVector &Operands, MCStreamer &Out,109 uint64_t &ErrorInfo,110 bool MatchingInlineAsm) override;111 112 MCRegister matchRegisterNameHelper(StringRef Name) const;113 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;114 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,115 SMLoc &EndLoc) override;116 117 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,118 SMLoc NameLoc, OperandVector &Operands) override;119 120 ParseStatus parseDirective(AsmToken DirectiveID) override;121 122 bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew,123 unsigned &Lmul, bool &Fractional, bool &TailAgnostic,124 bool &MaskAgnostic, bool &AltFmt);125 bool generateVTypeError(SMLoc ErrorLoc);126 127 bool generateXSfmmVTypeError(SMLoc ErrorLoc);128 // Helper to actually emit an instruction to the MCStreamer. Also, when129 // possible, compression of the instruction is performed.130 void emitToStreamer(MCStreamer &S, const MCInst &Inst);131 132 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that133 // synthesize the desired immediate value into the destination register.134 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);135 136 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement137 // helpers such as emitLoadLocalAddress and emitLoadAddress.138 void emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,139 const MCExpr *Symbol, RISCV::Specifier VKHi,140 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);141 142 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.143 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);144 145 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.146 void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);147 148 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.149 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);150 151 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS152 // addressing.153 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);154 155 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS156 // addressing.157 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);158 159 // Helper to emit pseudo load/store instruction with a symbol.160 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,161 MCStreamer &Out, bool HasTmpReg);162 163 // Helper to emit pseudo sign/zero extend instruction.164 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,165 SMLoc IDLoc, MCStreamer &Out);166 167 // Helper to emit pseudo vmsge{u}.vx instruction.168 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);169 170 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.171 // Enforcing this using a restricted register class for the second input172 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact173 // 'add' is an overloaded mnemonic.174 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);175 176 // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.177 // Enforcing this using a restricted register class for the output178 // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact179 // 'jalr' is an overloaded mnemonic.180 bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);181 182 // Check instruction constraints.183 bool validateInstruction(MCInst &Inst, OperandVector &Operands);184 185 /// Helper for processing MC instructions that have been successfully matched186 /// by matchAndEmitInstruction. Modifications to the emitted instructions,187 /// like the expansion of pseudo instructions (e.g., "li"), can be performed188 /// in this method.189 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,190 MCStreamer &Out);191 192// Auto-generated instruction matching functions193#define GET_ASSEMBLER_HEADER194#include "RISCVGenAsmMatcher.inc"195 196 ParseStatus parseCSRSystemRegister(OperandVector &Operands);197 ParseStatus parseFPImm(OperandVector &Operands);198 ParseStatus parseExpression(OperandVector &Operands);199 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);200 ParseStatus parseMemOpBaseReg(OperandVector &Operands);201 ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);202 ParseStatus parseOperandWithSpecifier(OperandVector &Operands);203 ParseStatus parseBareSymbol(OperandVector &Operands);204 ParseStatus parseCallSymbol(OperandVector &Operands);205 ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);206 ParseStatus parseJALOffset(OperandVector &Operands);207 ParseStatus parseVTypeI(OperandVector &Operands);208 ParseStatus parseMaskReg(OperandVector &Operands);209 ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);210 ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);211 ParseStatus parseGPRAsFPR(OperandVector &Operands);212 ParseStatus parseGPRAsFPR64(OperandVector &Operands);213 ParseStatus parseGPRPairAsFPR64(OperandVector &Operands);214 template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands);215 ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);216 ParseStatus parseFRMArg(OperandVector &Operands);217 ParseStatus parseFenceArg(OperandVector &Operands);218 ParseStatus parseRegList(OperandVector &Operands, bool MustIncludeS0 = false);219 ParseStatus parseRegListS0(OperandVector &Operands) {220 return parseRegList(Operands, /*MustIncludeS0=*/true);221 }222 223 ParseStatus parseRegReg(OperandVector &Operands);224 ParseStatus parseXSfmmVType(OperandVector &Operands);225 ParseStatus parseZcmpStackAdj(OperandVector &Operands,226 bool ExpectNegative = false);227 ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {228 return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);229 }230 231 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);232 bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);233 bool parseDataExpr(const MCExpr *&Res) override;234 235 bool parseDirectiveOption();236 bool parseDirectiveAttribute();237 bool parseDirectiveInsn(SMLoc L);238 bool parseDirectiveVariantCC();239 240 /// Helper to reset target features for a new arch string. It241 /// also records the new arch string that is expanded by RISCVISAInfo242 /// and reports error for invalid arch string.243 bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,244 bool FromOptionDirective);245 246 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {247 if (!(getSTI().hasFeature(Feature))) {248 MCSubtargetInfo &STI = copySTI();249 setAvailableFeatures(250 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));251 }252 }253 254 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {255 if (getSTI().hasFeature(Feature)) {256 MCSubtargetInfo &STI = copySTI();257 setAvailableFeatures(258 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));259 }260 }261 262 void pushFeatureBits() {263 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&264 "These two stacks must be kept synchronized");265 FeatureBitStack.push_back(getSTI().getFeatureBits());266 ParserOptionsStack.push_back(ParserOptions);267 }268 269 bool popFeatureBits() {270 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&271 "These two stacks must be kept synchronized");272 if (FeatureBitStack.empty())273 return true;274 275 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();276 copySTI().setFeatureBits(FeatureBits);277 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));278 279 ParserOptions = ParserOptionsStack.pop_back_val();280 281 return false;282 }283 284 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;285 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;286 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;287 288public:289 enum RISCVMatchResultTy : unsigned {290 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,291#define GET_OPERAND_DIAGNOSTIC_TYPES292#include "RISCVGenAsmMatcher.inc"293#undef GET_OPERAND_DIAGNOSTIC_TYPES294 };295 296 static bool classifySymbolRef(const MCExpr *Expr, RISCV::Specifier &Kind);297 static bool isSymbolDiff(const MCExpr *Expr);298 299 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,300 const MCInstrInfo &MII, const MCTargetOptions &Options)301 : MCTargetAsmParser(Options, STI, MII) {302 MCAsmParserExtension::Initialize(Parser);303 304 Parser.addAliasForDirective(".half", ".2byte");305 Parser.addAliasForDirective(".hword", ".2byte");306 Parser.addAliasForDirective(".word", ".4byte");307 Parser.addAliasForDirective(".dword", ".8byte");308 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));309 310 auto ABIName = StringRef(Options.ABIName);311 if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {312 errs() << "Hard-float 'f' ABI can't be used for a target that "313 "doesn't support the F instruction set extension (ignoring "314 "target-abi)\n";315 } else if (ABIName.ends_with("d") &&316 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {317 errs() << "Hard-float 'd' ABI can't be used for a target that "318 "doesn't support the D instruction set extension (ignoring "319 "target-abi)\n";320 }321 322 // Use computeTargetABI to check if ABIName is valid. If invalid, output323 // error message.324 RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(),325 ABIName);326 327 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();328 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();329 330 if (AddBuildAttributes)331 getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);332 }333};334 335/// RISCVOperand - Instances of this class represent a parsed machine336/// instruction337struct RISCVOperand final : public MCParsedAsmOperand {338 339 enum class KindTy {340 Token,341 Register,342 Expression,343 FPImmediate,344 SystemRegister,345 VType,346 FRM,347 Fence,348 RegList,349 StackAdj,350 RegReg,351 } Kind;352 353 struct RegOp {354 MCRegister Reg;355 bool IsGPRAsFPR;356 };357 358 struct ExprOp {359 const MCExpr *Expr;360 bool IsRV64;361 };362 363 struct FPImmOp {364 uint64_t Val;365 };366 367 struct SysRegOp {368 const char *Data;369 unsigned Length;370 unsigned Encoding;371 // FIXME: Add the Encoding parsed fields as needed for checks,372 // e.g.: read/write or user/supervisor/machine privileges.373 };374 375 struct VTypeOp {376 unsigned Val;377 };378 379 struct FRMOp {380 RISCVFPRndMode::RoundingMode FRM;381 };382 383 struct FenceOp {384 unsigned Val;385 };386 387 struct RegListOp {388 unsigned Encoding;389 };390 391 struct StackAdjOp {392 unsigned Val;393 };394 395 struct RegRegOp {396 MCRegister BaseReg;397 MCRegister OffsetReg;398 };399 400 SMLoc StartLoc, EndLoc;401 union {402 StringRef Tok;403 RegOp Reg;404 ExprOp Expr;405 FPImmOp FPImm;406 SysRegOp SysReg;407 VTypeOp VType;408 FRMOp FRM;409 FenceOp Fence;410 RegListOp RegList;411 StackAdjOp StackAdj;412 RegRegOp RegReg;413 };414 415 RISCVOperand(KindTy K) : Kind(K) {}416 417public:418 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {419 Kind = o.Kind;420 StartLoc = o.StartLoc;421 EndLoc = o.EndLoc;422 switch (Kind) {423 case KindTy::Register:424 Reg = o.Reg;425 break;426 case KindTy::Expression:427 Expr = o.Expr;428 break;429 case KindTy::FPImmediate:430 FPImm = o.FPImm;431 break;432 case KindTy::Token:433 Tok = o.Tok;434 break;435 case KindTy::SystemRegister:436 SysReg = o.SysReg;437 break;438 case KindTy::VType:439 VType = o.VType;440 break;441 case KindTy::FRM:442 FRM = o.FRM;443 break;444 case KindTy::Fence:445 Fence = o.Fence;446 break;447 case KindTy::RegList:448 RegList = o.RegList;449 break;450 case KindTy::StackAdj:451 StackAdj = o.StackAdj;452 break;453 case KindTy::RegReg:454 RegReg = o.RegReg;455 break;456 }457 }458 459 bool isToken() const override { return Kind == KindTy::Token; }460 bool isReg() const override { return Kind == KindTy::Register; }461 bool isExpr() const { return Kind == KindTy::Expression; }462 bool isV0Reg() const {463 return Kind == KindTy::Register && Reg.Reg == RISCV::V0;464 }465 bool isAnyReg() const {466 return Kind == KindTy::Register &&467 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.Reg) ||468 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.Reg) ||469 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.Reg));470 }471 bool isAnyRegC() const {472 return Kind == KindTy::Register &&473 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(Reg.Reg) ||474 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg.Reg));475 }476 bool isImm() const override { return isExpr(); }477 bool isMem() const override { return false; }478 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }479 bool isRegReg() const { return Kind == KindTy::RegReg; }480 bool isRegList() const { return Kind == KindTy::RegList; }481 bool isRegListS0() const {482 return Kind == KindTy::RegList && RegList.Encoding != RISCVZC::RA;483 }484 bool isStackAdj() const { return Kind == KindTy::StackAdj; }485 486 bool isGPR() const {487 return Kind == KindTy::Register &&488 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.Reg);489 }490 491 bool isGPRPair() const {492 return Kind == KindTy::Register &&493 RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg.Reg);494 }495 496 bool isGPRPairC() const {497 return Kind == KindTy::Register &&498 RISCVMCRegisterClasses[RISCV::GPRPairCRegClassID].contains(Reg.Reg);499 }500 501 bool isGPRPairNoX0() const {502 return Kind == KindTy::Register &&503 RISCVMCRegisterClasses[RISCV::GPRPairNoX0RegClassID].contains(504 Reg.Reg);505 }506 507 bool isGPRF16() const {508 return Kind == KindTy::Register &&509 RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(Reg.Reg);510 }511 512 bool isGPRF32() const {513 return Kind == KindTy::Register &&514 RISCVMCRegisterClasses[RISCV::GPRF32RegClassID].contains(Reg.Reg);515 }516 517 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }518 bool isGPRAsFPR16() const { return isGPRF16() && Reg.IsGPRAsFPR; }519 bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }520 bool isGPRPairAsFPR64() const { return isGPRPair() && Reg.IsGPRAsFPR; }521 522 static bool evaluateConstantExpr(const MCExpr *Expr, int64_t &Imm) {523 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {524 Imm = CE->getValue();525 return true;526 }527 528 return false;529 }530 531 // True if operand is a symbol with no modifiers, or a constant with no532 // modifiers and isShiftedInt<N-1, 1>(Op).533 template <int N> bool isBareSimmNLsb0() const {534 if (!isExpr())535 return false;536 537 int64_t Imm;538 if (evaluateConstantExpr(getExpr(), Imm))539 return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, isRV64Expr()));540 541 RISCV::Specifier VK = RISCV::S_None;542 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&543 VK == RISCV::S_None;544 }545 546 // True if operand is a symbol with no modifiers, or a constant with no547 // modifiers and isInt<N>(Op).548 template <int N> bool isBareSimmN() const {549 if (!isExpr())550 return false;551 552 int64_t Imm;553 if (evaluateConstantExpr(getExpr(), Imm))554 return isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));555 556 RISCV::Specifier VK = RISCV::S_None;557 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&558 VK == RISCV::S_None;559 }560 561 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td562 563 bool isBareSymbol() const {564 int64_t Imm;565 // Must be of 'immediate' type but not a constant.566 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))567 return false;568 569 RISCV::Specifier VK = RISCV::S_None;570 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&571 VK == RISCV::S_None;572 }573 574 bool isCallSymbol() const {575 int64_t Imm;576 // Must be of 'immediate' type but not a constant.577 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))578 return false;579 580 RISCV::Specifier VK = RISCV::S_None;581 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&582 VK == ELF::R_RISCV_CALL_PLT;583 }584 585 bool isPseudoJumpSymbol() const {586 int64_t Imm;587 // Must be of 'immediate' type but not a constant.588 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))589 return false;590 591 RISCV::Specifier VK = RISCV::S_None;592 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&593 VK == ELF::R_RISCV_CALL_PLT;594 }595 596 bool isTPRelAddSymbol() const {597 int64_t Imm;598 // Must be of 'immediate' type but not a constant.599 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))600 return false;601 602 RISCV::Specifier VK = RISCV::S_None;603 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&604 VK == ELF::R_RISCV_TPREL_ADD;605 }606 607 bool isTLSDESCCallSymbol() const {608 int64_t Imm;609 // Must be of 'immediate' type but not a constant.610 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))611 return false;612 613 RISCV::Specifier VK = RISCV::S_None;614 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&615 VK == ELF::R_RISCV_TLSDESC_CALL;616 }617 618 bool isCSRSystemRegister() const { return isSystemRegister(); }619 620 // If the last operand of the vsetvli/vsetvli instruction is a constant621 // expression, KindTy is Immediate.622 bool isVTypeI10() const {623 if (Kind == KindTy::VType)624 return true;625 return isUImm<10>();626 }627 bool isVTypeI11() const {628 if (Kind == KindTy::VType)629 return true;630 return isUImm<11>();631 }632 633 bool isXSfmmVType() const {634 return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VType.Val);635 }636 637 /// Return true if the operand is a valid for the fence instruction e.g.638 /// ('iorw').639 bool isFenceArg() const { return Kind == KindTy::Fence; }640 641 /// Return true if the operand is a valid floating point rounding mode.642 bool isFRMArg() const { return Kind == KindTy::FRM; }643 bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }644 bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }645 646 /// Return true if the operand is a valid fli.s floating-point immediate.647 bool isLoadFPImm() const {648 if (isExpr())649 return isUImm5();650 if (Kind != KindTy::FPImmediate)651 return false;652 int Idx = RISCVLoadFPImm::getLoadFPImm(653 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));654 // Don't allow decimal version of the minimum value. It is a different value655 // for each supported data type.656 return Idx >= 0 && Idx != 1;657 }658 659 bool isImmXLenLI() const {660 int64_t Imm;661 if (!isExpr())662 return false;663 // Given only Imm, ensuring that the actually specified constant is either664 // a signed or unsigned 64-bit number is unfortunately impossible.665 if (evaluateConstantExpr(getExpr(), Imm))666 return isRV64Expr() || (isInt<32>(Imm) || isUInt<32>(Imm));667 668 return RISCVAsmParser::isSymbolDiff(getExpr());669 }670 671 bool isImmXLenLI_Restricted() const {672 int64_t Imm;673 if (!isExpr())674 return false;675 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);676 // 'la imm' supports constant immediates only.677 return IsConstantImm &&678 (isRV64Expr() || (isInt<32>(Imm) || isUInt<32>(Imm)));679 }680 681 template <unsigned N> bool isUImm() const {682 int64_t Imm;683 if (!isExpr())684 return false;685 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);686 return IsConstantImm && isUInt<N>(Imm);687 }688 689 template <unsigned N, unsigned S> bool isUImmShifted() const {690 int64_t Imm;691 if (!isExpr())692 return false;693 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);694 return IsConstantImm && isShiftedUInt<N, S>(Imm);695 }696 697 template <class Pred> bool isUImmPred(Pred p) const {698 int64_t Imm;699 if (!isExpr())700 return false;701 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);702 return IsConstantImm && p(Imm);703 }704 705 bool isUImmLog2XLen() const {706 if (isExpr() && isRV64Expr())707 return isUImm<6>();708 return isUImm<5>();709 }710 711 bool isUImmLog2XLenNonZero() const {712 if (isExpr() && isRV64Expr())713 return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<6>(Imm); });714 return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });715 }716 717 bool isUImmLog2XLenHalf() const {718 if (isExpr() && isRV64Expr())719 return isUImm<5>();720 return isUImm<4>();721 }722 723 bool isUImm1() const { return isUImm<1>(); }724 bool isUImm2() const { return isUImm<2>(); }725 bool isUImm3() const { return isUImm<3>(); }726 bool isUImm4() const { return isUImm<4>(); }727 bool isUImm5() const { return isUImm<5>(); }728 bool isUImm6() const { return isUImm<6>(); }729 bool isUImm7() const { return isUImm<7>(); }730 bool isUImm8() const { return isUImm<8>(); }731 bool isUImm9() const { return isUImm<9>(); }732 bool isUImm10() const { return isUImm<10>(); }733 bool isUImm11() const { return isUImm<11>(); }734 bool isUImm16() const { return isUImm<16>(); }735 bool isUImm20() const { return isUImm<20>(); }736 bool isUImm32() const { return isUImm<32>(); }737 bool isUImm48() const { return isUImm<48>(); }738 bool isUImm64() const { return isUImm<64>(); }739 740 bool isUImm5NonZero() const {741 return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });742 }743 744 bool isUImm5GT3() const {745 return isUImmPred([](int64_t Imm) { return isUInt<5>(Imm) && Imm > 3; });746 }747 748 bool isUImm5Plus1() const {749 return isUImmPred(750 [](int64_t Imm) { return Imm > 0 && isUInt<5>(Imm - 1); });751 }752 753 bool isUImm5GE6Plus1() const {754 return isUImmPred(755 [](int64_t Imm) { return Imm >= 6 && isUInt<5>(Imm - 1); });756 }757 758 bool isUImm5Slist() const {759 return isUImmPred([](int64_t Imm) {760 return (Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||761 (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31);762 });763 }764 765 bool isUImm8GE32() const {766 return isUImmPred([](int64_t Imm) { return isUInt<8>(Imm) && Imm >= 32; });767 }768 769 bool isRnumArg() const {770 return isUImmPred(771 [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(10); });772 }773 774 bool isRnumArg_0_7() const {775 return isUImmPred(776 [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(7); });777 }778 779 bool isRnumArg_1_10() const {780 return isUImmPred(781 [](int64_t Imm) { return Imm >= INT64_C(1) && Imm <= INT64_C(10); });782 }783 784 bool isRnumArg_2_14() const {785 return isUImmPred(786 [](int64_t Imm) { return Imm >= INT64_C(2) && Imm <= INT64_C(14); });787 }788 789 template <unsigned N> bool isSImm() const {790 int64_t Imm;791 if (!isExpr())792 return false;793 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);794 return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));795 }796 797 template <class Pred> bool isSImmPred(Pred p) const {798 int64_t Imm;799 if (!isExpr())800 return false;801 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);802 return IsConstantImm && p(fixImmediateForRV32(Imm, isRV64Expr()));803 }804 805 bool isSImm5() const { return isSImm<5>(); }806 bool isSImm6() const { return isSImm<6>(); }807 bool isSImm10() const { return isSImm<10>(); }808 bool isSImm11() const { return isSImm<11>(); }809 bool isSImm12() const { return isSImm<12>(); }810 bool isSImm16() const { return isSImm<16>(); }811 bool isSImm26() const { return isSImm<26>(); }812 813 bool isSImm5NonZero() const {814 return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<5>(Imm); });815 }816 817 bool isSImm6NonZero() const {818 return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<6>(Imm); });819 }820 821 bool isCLUIImm() const {822 return isUImmPred([](int64_t Imm) {823 return (isUInt<5>(Imm) && Imm != 0) || (Imm >= 0xfffe0 && Imm <= 0xfffff);824 });825 }826 827 bool isUImm2Lsb0() const { return isUImmShifted<1, 1>(); }828 829 bool isUImm5Lsb0() const { return isUImmShifted<4, 1>(); }830 831 bool isUImm6Lsb0() const { return isUImmShifted<5, 1>(); }832 833 bool isUImm7Lsb00() const { return isUImmShifted<5, 2>(); }834 835 bool isUImm7Lsb000() const { return isUImmShifted<4, 3>(); }836 837 bool isUImm8Lsb00() const { return isUImmShifted<6, 2>(); }838 839 bool isUImm8Lsb000() const { return isUImmShifted<5, 3>(); }840 841 bool isUImm9Lsb000() const { return isUImmShifted<6, 3>(); }842 843 bool isUImm14Lsb00() const { return isUImmShifted<12, 2>(); }844 845 bool isUImm10Lsb00NonZero() const {846 return isUImmPred(847 [](int64_t Imm) { return isShiftedUInt<8, 2>(Imm) && (Imm != 0); });848 }849 850 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.851 // This allows writing 'addi a0, a0, 0xffffffff'.852 static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {853 if (IsRV64Imm || !isUInt<32>(Imm))854 return Imm;855 return SignExtend64<32>(Imm);856 }857 858 bool isSImm12LO() const {859 if (!isExpr())860 return false;861 862 int64_t Imm;863 if (evaluateConstantExpr(getExpr(), Imm))864 return isInt<12>(fixImmediateForRV32(Imm, isRV64Expr()));865 866 RISCV::Specifier VK = RISCV::S_None;867 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&868 (VK == RISCV::S_LO || VK == RISCV::S_PCREL_LO ||869 VK == RISCV::S_TPREL_LO || VK == ELF::R_RISCV_TLSDESC_LOAD_LO12 ||870 VK == ELF::R_RISCV_TLSDESC_ADD_LO12);871 }872 873 bool isSImm12Lsb00000() const {874 return isSImmPred([](int64_t Imm) { return isShiftedInt<7, 5>(Imm); });875 }876 877 bool isSImm10Lsb0000NonZero() const {878 return isSImmPred(879 [](int64_t Imm) { return Imm != 0 && isShiftedInt<6, 4>(Imm); });880 }881 882 bool isSImm16NonZero() const {883 return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<16>(Imm); });884 }885 886 bool isUImm16NonZero() const {887 return isUImmPred([](int64_t Imm) { return isUInt<16>(Imm) && Imm != 0; });888 }889 890 bool isSImm20LI() const {891 if (!isExpr())892 return false;893 894 int64_t Imm;895 if (evaluateConstantExpr(getExpr(), Imm))896 return isInt<20>(fixImmediateForRV32(Imm, isRV64Expr()));897 898 RISCV::Specifier VK = RISCV::S_None;899 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&900 VK == RISCV::S_QC_ABS20;901 }902 903 bool isSImm8Unsigned() const { return isSImm<8>() || isUImm<8>(); }904 bool isSImm10Unsigned() const { return isSImm<10>() || isUImm<10>(); }905 906 bool isUImm20LUI() const {907 if (!isExpr())908 return false;909 910 int64_t Imm;911 if (evaluateConstantExpr(getExpr(), Imm))912 return isUInt<20>(Imm);913 914 RISCV::Specifier VK = RISCV::S_None;915 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&916 (VK == ELF::R_RISCV_HI20 || VK == ELF::R_RISCV_TPREL_HI20);917 }918 919 bool isUImm20AUIPC() const {920 if (!isExpr())921 return false;922 923 int64_t Imm;924 if (evaluateConstantExpr(getExpr(), Imm))925 return isUInt<20>(Imm);926 927 RISCV::Specifier VK = RISCV::S_None;928 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&929 (VK == ELF::R_RISCV_PCREL_HI20 || VK == ELF::R_RISCV_GOT_HI20 ||930 VK == ELF::R_RISCV_TLS_GOT_HI20 || VK == ELF::R_RISCV_TLS_GD_HI20 ||931 VK == ELF::R_RISCV_TLSDESC_HI20);932 }933 934 bool isImmZero() const {935 return isUImmPred([](int64_t Imm) { return 0 == Imm; });936 }937 938 bool isImmThree() const {939 return isUImmPred([](int64_t Imm) { return 3 == Imm; });940 }941 942 bool isImmFour() const {943 return isUImmPred([](int64_t Imm) { return 4 == Imm; });944 }945 946 bool isImm5Zibi() const {947 return isUImmPred(948 [](int64_t Imm) { return (Imm != 0 && isUInt<5>(Imm)) || Imm == -1; });949 }950 951 bool isSImm5Plus1() const {952 return isSImmPred(953 [](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });954 }955 956 bool isSImm18() const {957 return isSImmPred([](int64_t Imm) { return isInt<18>(Imm); });958 }959 960 bool isSImm18Lsb0() const {961 return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 1>(Imm); });962 }963 964 bool isSImm19Lsb00() const {965 return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 2>(Imm); });966 }967 968 bool isSImm20Lsb000() const {969 return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 3>(Imm); });970 }971 972 bool isSImm32Lsb0() const {973 return isSImmPred([](int64_t Imm) { return isShiftedInt<31, 1>(Imm); });974 }975 976 /// getStartLoc - Gets location of the first token of this operand977 SMLoc getStartLoc() const override { return StartLoc; }978 /// getEndLoc - Gets location of the last token of this operand979 SMLoc getEndLoc() const override { return EndLoc; }980 981 /// True if this operand is for an RV64 instruction982 bool isRV64Expr() const {983 assert(Kind == KindTy::Expression && "Invalid type access!");984 return Expr.IsRV64;985 }986 987 MCRegister getReg() const override {988 assert(Kind == KindTy::Register && "Invalid type access!");989 return Reg.Reg;990 }991 992 StringRef getSysReg() const {993 assert(Kind == KindTy::SystemRegister && "Invalid type access!");994 return StringRef(SysReg.Data, SysReg.Length);995 }996 997 const MCExpr *getExpr() const {998 assert(Kind == KindTy::Expression && "Invalid type access!");999 return Expr.Expr;1000 }1001 1002 uint64_t getFPConst() const {1003 assert(Kind == KindTy::FPImmediate && "Invalid type access!");1004 return FPImm.Val;1005 }1006 1007 StringRef getToken() const {1008 assert(Kind == KindTy::Token && "Invalid type access!");1009 return Tok;1010 }1011 1012 unsigned getVType() const {1013 assert(Kind == KindTy::VType && "Invalid type access!");1014 return VType.Val;1015 }1016 1017 RISCVFPRndMode::RoundingMode getFRM() const {1018 assert(Kind == KindTy::FRM && "Invalid type access!");1019 return FRM.FRM;1020 }1021 1022 unsigned getFence() const {1023 assert(Kind == KindTy::Fence && "Invalid type access!");1024 return Fence.Val;1025 }1026 1027 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {1028 auto RegName = [](MCRegister Reg) {1029 if (Reg)1030 return RISCVInstPrinter::getRegisterName(Reg);1031 else1032 return "noreg";1033 };1034 1035 switch (Kind) {1036 case KindTy::Expression:1037 OS << "<imm: ";1038 MAI.printExpr(OS, *Expr.Expr);1039 OS << ' ' << (Expr.IsRV64 ? "rv64" : "rv32") << '>';1040 break;1041 case KindTy::FPImmediate:1042 OS << "<fpimm: " << FPImm.Val << ">";1043 break;1044 case KindTy::Register:1045 OS << "<reg: " << RegName(Reg.Reg) << " (" << Reg.Reg.id()1046 << (Reg.IsGPRAsFPR ? ") GPRasFPR>" : ")>");1047 break;1048 case KindTy::Token:1049 OS << "'" << getToken() << "'";1050 break;1051 case KindTy::SystemRegister:1052 OS << "<sysreg: " << getSysReg() << " (" << SysReg.Encoding << ")>";1053 break;1054 case KindTy::VType:1055 OS << "<vtype: ";1056 RISCVVType::printVType(getVType(), OS);1057 OS << '>';1058 break;1059 case KindTy::FRM:1060 OS << "<frm: ";1061 roundingModeToString(getFRM());1062 OS << '>';1063 break;1064 case KindTy::Fence:1065 OS << "<fence: ";1066 OS << getFence();1067 OS << '>';1068 break;1069 case KindTy::RegList:1070 OS << "<reglist: ";1071 RISCVZC::printRegList(RegList.Encoding, OS);1072 OS << '>';1073 break;1074 case KindTy::StackAdj:1075 OS << "<stackadj: ";1076 OS << StackAdj.Val;1077 OS << '>';1078 break;1079 case KindTy::RegReg:1080 OS << "<RegReg: BaseReg " << RegName(RegReg.BaseReg) << " OffsetReg "1081 << RegName(RegReg.OffsetReg);1082 break;1083 }1084 }1085 1086 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {1087 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);1088 Op->Tok = Str;1089 Op->StartLoc = S;1090 Op->EndLoc = S;1091 return Op;1092 }1093 1094 static std::unique_ptr<RISCVOperand>1095 createReg(MCRegister Reg, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {1096 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);1097 Op->Reg.Reg = Reg;1098 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;1099 Op->StartLoc = S;1100 Op->EndLoc = E;1101 return Op;1102 }1103 1104 static std::unique_ptr<RISCVOperand> createExpr(const MCExpr *Val, SMLoc S,1105 SMLoc E, bool IsRV64) {1106 auto Op = std::make_unique<RISCVOperand>(KindTy::Expression);1107 Op->Expr.Expr = Val;1108 Op->Expr.IsRV64 = IsRV64;1109 Op->StartLoc = S;1110 Op->EndLoc = E;1111 return Op;1112 }1113 1114 static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {1115 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);1116 Op->FPImm.Val = Val;1117 Op->StartLoc = S;1118 Op->EndLoc = S;1119 return Op;1120 }1121 1122 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,1123 unsigned Encoding) {1124 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);1125 Op->SysReg.Data = Str.data();1126 Op->SysReg.Length = Str.size();1127 Op->SysReg.Encoding = Encoding;1128 Op->StartLoc = S;1129 Op->EndLoc = S;1130 return Op;1131 }1132 1133 static std::unique_ptr<RISCVOperand>1134 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {1135 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);1136 Op->FRM.FRM = FRM;1137 Op->StartLoc = S;1138 Op->EndLoc = S;1139 return Op;1140 }1141 1142 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {1143 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);1144 Op->Fence.Val = Val;1145 Op->StartLoc = S;1146 Op->EndLoc = S;1147 return Op;1148 }1149 1150 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {1151 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);1152 Op->VType.Val = VTypeI;1153 Op->StartLoc = S;1154 Op->EndLoc = S;1155 return Op;1156 }1157 1158 static std::unique_ptr<RISCVOperand> createRegList(unsigned RlistEncode,1159 SMLoc S) {1160 auto Op = std::make_unique<RISCVOperand>(KindTy::RegList);1161 Op->RegList.Encoding = RlistEncode;1162 Op->StartLoc = S;1163 return Op;1164 }1165 1166 static std::unique_ptr<RISCVOperand>1167 createRegReg(MCRegister BaseReg, MCRegister OffsetReg, SMLoc S) {1168 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);1169 Op->RegReg.BaseReg = BaseReg;1170 Op->RegReg.OffsetReg = OffsetReg;1171 Op->StartLoc = S;1172 Op->EndLoc = S;1173 return Op;1174 }1175 1176 static std::unique_ptr<RISCVOperand> createStackAdj(unsigned StackAdj, SMLoc S) {1177 auto Op = std::make_unique<RISCVOperand>(KindTy::StackAdj);1178 Op->StackAdj.Val = StackAdj;1179 Op->StartLoc = S;1180 return Op;1181 }1182 1183 static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {1184 assert(Expr && "Expr shouldn't be null!");1185 int64_t Imm = 0;1186 bool IsConstant = evaluateConstantExpr(Expr, Imm);1187 1188 if (IsConstant)1189 Inst.addOperand(1190 MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));1191 else1192 Inst.addOperand(MCOperand::createExpr(Expr));1193 }1194 1195 // Used by the TableGen Code1196 void addRegOperands(MCInst &Inst, unsigned N) const {1197 assert(N == 1 && "Invalid number of operands!");1198 Inst.addOperand(MCOperand::createReg(getReg()));1199 }1200 1201 void addImmOperands(MCInst &Inst, unsigned N) const {1202 assert(N == 1 && "Invalid number of operands!");1203 addExpr(Inst, getExpr(), isRV64Expr());1204 }1205 1206 void addSImm8UnsignedOperands(MCInst &Inst, unsigned N) const {1207 assert(N == 1 && "Invalid number of operands!");1208 int64_t Imm;1209 [[maybe_unused]] bool IsConstant = evaluateConstantExpr(getExpr(), Imm);1210 assert(IsConstant);1211 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));1212 }1213 1214 void addSImm10UnsignedOperands(MCInst &Inst, unsigned N) const {1215 assert(N == 1 && "Invalid number of operands!");1216 int64_t Imm;1217 [[maybe_unused]] bool IsConstant = evaluateConstantExpr(getExpr(), Imm);1218 assert(IsConstant);1219 Inst.addOperand(MCOperand::createImm(SignExtend64<10>(Imm)));1220 }1221 1222 void addFPImmOperands(MCInst &Inst, unsigned N) const {1223 assert(N == 1 && "Invalid number of operands!");1224 if (isExpr()) {1225 addExpr(Inst, getExpr(), isRV64Expr());1226 return;1227 }1228 1229 int Imm = RISCVLoadFPImm::getLoadFPImm(1230 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));1231 Inst.addOperand(MCOperand::createImm(Imm));1232 }1233 1234 void addFenceArgOperands(MCInst &Inst, unsigned N) const {1235 assert(N == 1 && "Invalid number of operands!");1236 Inst.addOperand(MCOperand::createImm(Fence.Val));1237 }1238 1239 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {1240 assert(N == 1 && "Invalid number of operands!");1241 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));1242 }1243 1244 // Support non-canonical syntax:1245 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"1246 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"1247 void addVTypeIOperands(MCInst &Inst, unsigned N) const {1248 assert(N == 1 && "Invalid number of operands!");1249 int64_t Imm = 0;1250 if (Kind == KindTy::Expression) {1251 [[maybe_unused]] bool IsConstantImm =1252 evaluateConstantExpr(getExpr(), Imm);1253 assert(IsConstantImm && "Invalid VTypeI Operand!");1254 } else {1255 Imm = getVType();1256 }1257 Inst.addOperand(MCOperand::createImm(Imm));1258 }1259 1260 void addRegListOperands(MCInst &Inst, unsigned N) const {1261 assert(N == 1 && "Invalid number of operands!");1262 Inst.addOperand(MCOperand::createImm(RegList.Encoding));1263 }1264 1265 void addRegRegOperands(MCInst &Inst, unsigned N) const {1266 assert(N == 2 && "Invalid number of operands!");1267 Inst.addOperand(MCOperand::createReg(RegReg.BaseReg));1268 Inst.addOperand(MCOperand::createReg(RegReg.OffsetReg));1269 }1270 1271 void addStackAdjOperands(MCInst &Inst, unsigned N) const {1272 assert(N == 1 && "Invalid number of operands!");1273 Inst.addOperand(MCOperand::createImm(StackAdj.Val));1274 }1275 1276 void addFRMArgOperands(MCInst &Inst, unsigned N) const {1277 assert(N == 1 && "Invalid number of operands!");1278 Inst.addOperand(MCOperand::createImm(getFRM()));1279 }1280};1281} // end anonymous namespace.1282 1283#define GET_REGISTER_MATCHER1284#define GET_SUBTARGET_FEATURE_NAME1285#define GET_MATCHER_IMPLEMENTATION1286#define GET_MNEMONIC_SPELL_CHECKER1287#include "RISCVGenAsmMatcher.inc"1288 1289static MCRegister convertFPR64ToFPR16(MCRegister Reg) {1290 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");1291 return Reg - RISCV::F0_D + RISCV::F0_H;1292}1293 1294static MCRegister convertFPR64ToFPR32(MCRegister Reg) {1295 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");1296 return Reg - RISCV::F0_D + RISCV::F0_F;1297}1298 1299static MCRegister convertFPR64ToFPR128(MCRegister Reg) {1300 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");1301 return Reg - RISCV::F0_D + RISCV::F0_Q;1302}1303 1304static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,1305 unsigned Kind) {1306 unsigned RegClassID;1307 if (Kind == MCK_VRM2)1308 RegClassID = RISCV::VRM2RegClassID;1309 else if (Kind == MCK_VRM4)1310 RegClassID = RISCV::VRM4RegClassID;1311 else if (Kind == MCK_VRM8)1312 RegClassID = RISCV::VRM8RegClassID;1313 else1314 return MCRegister();1315 return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,1316 &RISCVMCRegisterClasses[RegClassID]);1317}1318 1319unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,1320 unsigned Kind) {1321 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);1322 if (!Op.isReg())1323 return Match_InvalidOperand;1324 1325 MCRegister Reg = Op.getReg();1326 bool IsRegFPR64 =1327 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);1328 bool IsRegFPR64C =1329 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);1330 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);1331 1332 if (IsRegFPR64 && Kind == MCK_FPR128) {1333 Op.Reg.Reg = convertFPR64ToFPR128(Reg);1334 return Match_Success;1335 }1336 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the1337 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.1338 if ((IsRegFPR64 && Kind == MCK_FPR32) ||1339 (IsRegFPR64C && Kind == MCK_FPR32C)) {1340 Op.Reg.Reg = convertFPR64ToFPR32(Reg);1341 return Match_Success;1342 }1343 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the1344 // register from FPR64 to FPR16 if necessary.1345 if (IsRegFPR64 && Kind == MCK_FPR16) {1346 Op.Reg.Reg = convertFPR64ToFPR16(Reg);1347 return Match_Success;1348 }1349 if (Kind == MCK_GPRAsFPR16 && Op.isGPRAsFPR()) {1350 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_H;1351 return Match_Success;1352 }1353 if (Kind == MCK_GPRAsFPR32 && Op.isGPRAsFPR()) {1354 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_W;1355 return Match_Success;1356 }1357 1358 // There are some GPRF64AsFPR instructions that have no RV32 equivalent. We1359 // reject them at parsing thinking we should match as GPRPairAsFPR for RV32.1360 // So we explicitly accept them here for RV32 to allow the generic code to1361 // report that the instruction requires RV64.1362 if (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg) &&1363 Kind == MCK_GPRF64AsFPR && STI->hasFeature(RISCV::FeatureStdExtZdinx) &&1364 !isRV64())1365 return Match_Success;1366 1367 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce1368 // the register from VR to VRM2/VRM4/VRM8 if necessary.1369 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {1370 Op.Reg.Reg = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);1371 if (!Op.Reg.Reg)1372 return Match_InvalidOperand;1373 return Match_Success;1374 }1375 return Match_InvalidOperand;1376}1377 1378bool RISCVAsmParser::generateImmOutOfRangeError(1379 SMLoc ErrorLoc, int64_t Lower, int64_t Upper,1380 const Twine &Msg = "immediate must be an integer in the range") {1381 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");1382}1383 1384bool RISCVAsmParser::generateImmOutOfRangeError(1385 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,1386 const Twine &Msg = "immediate must be an integer in the range") {1387 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1388 return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);1389}1390 1391bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,1392 OperandVector &Operands,1393 MCStreamer &Out,1394 uint64_t &ErrorInfo,1395 bool MatchingInlineAsm) {1396 MCInst Inst;1397 FeatureBitset MissingFeatures;1398 1399 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,1400 MatchingInlineAsm);1401 switch (Result) {1402 default:1403 break;1404 case Match_Success:1405 if (validateInstruction(Inst, Operands))1406 return true;1407 return processInstruction(Inst, IDLoc, Operands, Out);1408 case Match_MissingFeature: {1409 assert(MissingFeatures.any() && "Unknown missing features!");1410 bool FirstFeature = true;1411 std::string Msg = "instruction requires the following:";1412 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {1413 if (MissingFeatures[i]) {1414 Msg += FirstFeature ? " " : ", ";1415 Msg += getSubtargetFeatureName(i);1416 FirstFeature = false;1417 }1418 }1419 return Error(IDLoc, Msg);1420 }1421 case Match_MnemonicFail: {1422 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());1423 std::string Suggestion = RISCVMnemonicSpellCheck(1424 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);1425 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);1426 }1427 case Match_InvalidOperand: {1428 SMLoc ErrorLoc = IDLoc;1429 if (ErrorInfo != ~0ULL) {1430 if (ErrorInfo >= Operands.size())1431 return Error(ErrorLoc, "too few operands for instruction");1432 1433 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1434 if (ErrorLoc == SMLoc())1435 ErrorLoc = IDLoc;1436 }1437 return Error(ErrorLoc, "invalid operand for instruction");1438 }1439 }1440 1441 // Handle the case when the error message is of specific type1442 // other than the generic Match_InvalidOperand, and the1443 // corresponding operand is missing.1444 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {1445 SMLoc ErrorLoc = IDLoc;1446 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())1447 return Error(ErrorLoc, "too few operands for instruction");1448 }1449 1450 switch (Result) {1451 default:1452 break;1453 case Match_InvalidImmXLenLI:1454 if (isRV64()) {1455 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1456 return Error(ErrorLoc, "operand must be a constant 64-bit integer");1457 }1458 return generateImmOutOfRangeError(Operands, ErrorInfo,1459 std::numeric_limits<int32_t>::min(),1460 std::numeric_limits<uint32_t>::max());1461 case Match_InvalidImmXLenLI_Restricted:1462 if (isRV64()) {1463 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1464 return Error(ErrorLoc, "operand either must be a constant 64-bit integer "1465 "or a bare symbol name");1466 }1467 return generateImmOutOfRangeError(1468 Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),1469 std::numeric_limits<uint32_t>::max(),1470 "operand either must be a bare symbol name or an immediate integer in "1471 "the range");1472 case Match_InvalidUImmLog2XLen:1473 if (isRV64())1474 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);1475 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);1476 case Match_InvalidUImmLog2XLenNonZero:1477 if (isRV64())1478 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);1479 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);1480 case Match_InvalidUImm1:1481 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);1482 case Match_InvalidUImm2:1483 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);1484 case Match_InvalidUImm2Lsb0:1485 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,1486 "immediate must be one of");1487 case Match_InvalidUImm3:1488 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);1489 case Match_InvalidUImm4:1490 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);1491 case Match_InvalidUImm5:1492 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);1493 case Match_InvalidUImm5NonZero:1494 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);1495 case Match_InvalidUImm5GT3:1496 return generateImmOutOfRangeError(Operands, ErrorInfo, 4, (1 << 5) - 1);1497 case Match_InvalidUImm5Plus1:1498 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));1499 case Match_InvalidUImm5GE6Plus1:1500 return generateImmOutOfRangeError(Operands, ErrorInfo, 6, (1 << 5));1501 case Match_InvalidUImm5Slist: {1502 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1503 return Error(ErrorLoc,1504 "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");1505 }1506 case Match_InvalidUImm6:1507 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);1508 case Match_InvalidUImm7:1509 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);1510 case Match_InvalidUImm8:1511 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);1512 case Match_InvalidUImm8GE32:1513 return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);1514 case Match_InvalidSImm5:1515 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),1516 (1 << 4) - 1);1517 case Match_InvalidSImm5NonZero:1518 return generateImmOutOfRangeError(1519 Operands, ErrorInfo, -(1 << 4), (1 << 4) - 1,1520 "immediate must be non-zero in the range");1521 case Match_InvalidSImm6:1522 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),1523 (1 << 5) - 1);1524 case Match_InvalidSImm6NonZero:1525 return generateImmOutOfRangeError(1526 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,1527 "immediate must be non-zero in the range");1528 case Match_InvalidCLUIImm:1529 return generateImmOutOfRangeError(1530 Operands, ErrorInfo, 1, (1 << 5) - 1,1531 "immediate must be in [0xfffe0, 0xfffff] or");1532 case Match_InvalidUImm5Lsb0:1533 return generateImmOutOfRangeError(1534 Operands, ErrorInfo, 0, (1 << 5) - 2,1535 "immediate must be a multiple of 2 bytes in the range");1536 case Match_InvalidUImm6Lsb0:1537 return generateImmOutOfRangeError(1538 Operands, ErrorInfo, 0, (1 << 6) - 2,1539 "immediate must be a multiple of 2 bytes in the range");1540 case Match_InvalidUImm7Lsb00:1541 return generateImmOutOfRangeError(1542 Operands, ErrorInfo, 0, (1 << 7) - 4,1543 "immediate must be a multiple of 4 bytes in the range");1544 case Match_InvalidUImm8Lsb00:1545 return generateImmOutOfRangeError(1546 Operands, ErrorInfo, 0, (1 << 8) - 4,1547 "immediate must be a multiple of 4 bytes in the range");1548 case Match_InvalidUImm8Lsb000:1549 return generateImmOutOfRangeError(1550 Operands, ErrorInfo, 0, (1 << 8) - 8,1551 "immediate must be a multiple of 8 bytes in the range");1552 case Match_InvalidUImm9:1553 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 9) - 1,1554 "immediate offset must be in the range");1555 case Match_InvalidBareSImm9Lsb0:1556 return generateImmOutOfRangeError(1557 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,1558 "immediate must be a multiple of 2 bytes in the range");1559 case Match_InvalidUImm9Lsb000:1560 return generateImmOutOfRangeError(1561 Operands, ErrorInfo, 0, (1 << 9) - 8,1562 "immediate must be a multiple of 8 bytes in the range");1563 case Match_InvalidSImm8Unsigned:1564 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),1565 (1 << 8) - 1);1566 case Match_InvalidSImm10:1567 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 9),1568 (1 << 9) - 1);1569 case Match_InvalidSImm10Unsigned:1570 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 9),1571 (1 << 10) - 1);1572 case Match_InvalidUImm10Lsb00NonZero:1573 return generateImmOutOfRangeError(1574 Operands, ErrorInfo, 4, (1 << 10) - 4,1575 "immediate must be a multiple of 4 bytes in the range");1576 case Match_InvalidSImm10Lsb0000NonZero:1577 return generateImmOutOfRangeError(1578 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,1579 "immediate must be a multiple of 16 bytes and non-zero in the range");1580 case Match_InvalidSImm11:1581 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),1582 (1 << 10) - 1);1583 case Match_InvalidBareSImm11Lsb0:1584 return generateImmOutOfRangeError(1585 Operands, ErrorInfo, -(1 << 10), (1 << 10) - 2,1586 "immediate must be a multiple of 2 bytes in the range");1587 case Match_InvalidUImm10:1588 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 10) - 1);1589 case Match_InvalidUImm11:1590 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 11) - 1);1591 case Match_InvalidUImm14Lsb00:1592 return generateImmOutOfRangeError(1593 Operands, ErrorInfo, 0, (1 << 14) - 4,1594 "immediate must be a multiple of 4 bytes in the range");1595 case Match_InvalidUImm16NonZero:1596 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16) - 1);1597 case Match_InvalidSImm12:1598 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),1599 (1 << 11) - 1);1600 case Match_InvalidSImm12LO:1601 return generateImmOutOfRangeError(1602 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,1603 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo specifier or an "1604 "integer in the range");1605 case Match_InvalidBareSImm12Lsb0:1606 return generateImmOutOfRangeError(1607 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,1608 "immediate must be a multiple of 2 bytes in the range");1609 case Match_InvalidSImm12Lsb00000:1610 return generateImmOutOfRangeError(1611 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,1612 "immediate must be a multiple of 32 bytes in the range");1613 case Match_InvalidBareSImm13Lsb0:1614 return generateImmOutOfRangeError(1615 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,1616 "immediate must be a multiple of 2 bytes in the range");1617 case Match_InvalidSImm16:1618 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 15),1619 (1 << 15) - 1);1620 case Match_InvalidSImm16NonZero:1621 return generateImmOutOfRangeError(1622 Operands, ErrorInfo, -(1 << 15), (1 << 15) - 1,1623 "immediate must be non-zero in the range");1624 case Match_InvalidSImm20LI:1625 return generateImmOutOfRangeError(1626 Operands, ErrorInfo, -(1 << 19), (1 << 19) - 1,1627 "operand must be a symbol with a %qc.abs20 specifier or an integer "1628 " in the range");1629 case Match_InvalidUImm20LUI:1630 return generateImmOutOfRangeError(1631 Operands, ErrorInfo, 0, (1 << 20) - 1,1632 "operand must be a symbol with "1633 "%hi/%tprel_hi specifier or an integer in "1634 "the range");1635 case Match_InvalidUImm20:1636 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);1637 case Match_InvalidUImm20AUIPC:1638 return generateImmOutOfRangeError(1639 Operands, ErrorInfo, 0, (1 << 20) - 1,1640 "operand must be a symbol with a "1641 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi specifier "1642 "or "1643 "an integer in the range");1644 case Match_InvalidBareSImm21Lsb0:1645 return generateImmOutOfRangeError(1646 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,1647 "immediate must be a multiple of 2 bytes in the range");1648 case Match_InvalidCSRSystemRegister: {1649 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,1650 "operand must be a valid system register "1651 "name or an integer in the range");1652 }1653 case Match_InvalidImm5Zibi:1654 return generateImmOutOfRangeError(1655 Operands, ErrorInfo, -1, (1 << 5) - 1,1656 "immediate must be non-zero in the range");1657 case Match_InvalidVTypeI: {1658 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1659 return generateVTypeError(ErrorLoc);1660 }1661 case Match_InvalidSImm5Plus1: {1662 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,1663 (1 << 4),1664 "immediate must be in the range");1665 }1666 case Match_InvalidSImm18:1667 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 17),1668 (1 << 17) - 1);1669 case Match_InvalidSImm18Lsb0:1670 return generateImmOutOfRangeError(1671 Operands, ErrorInfo, -(1 << 17), (1 << 17) - 2,1672 "immediate must be a multiple of 2 bytes in the range");1673 case Match_InvalidSImm19Lsb00:1674 return generateImmOutOfRangeError(1675 Operands, ErrorInfo, -(1 << 18), (1 << 18) - 4,1676 "immediate must be a multiple of 4 bytes in the range");1677 case Match_InvalidSImm20Lsb000:1678 return generateImmOutOfRangeError(1679 Operands, ErrorInfo, -(1 << 19), (1 << 19) - 8,1680 "immediate must be a multiple of 8 bytes in the range");1681 case Match_InvalidSImm26:1682 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 25),1683 (1 << 25) - 1);1684 // HACK: See comment before `BareSymbolQC_E_LI` in RISCVInstrInfoXqci.td.1685 case Match_InvalidBareSymbolQC_E_LI:1686 [[fallthrough]];1687 // END HACK1688 case Match_InvalidBareSImm32:1689 return generateImmOutOfRangeError(Operands, ErrorInfo,1690 std::numeric_limits<int32_t>::min(),1691 std::numeric_limits<uint32_t>::max());1692 case Match_InvalidBareSImm32Lsb0:1693 return generateImmOutOfRangeError(1694 Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),1695 std::numeric_limits<int32_t>::max() - 1,1696 "operand must be a multiple of 2 bytes in the range");1697 case Match_InvalidRnumArg: {1698 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);1699 }1700 case Match_InvalidStackAdj: {1701 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1702 return Error(1703 ErrorLoc,1704 "stack adjustment is invalid for this instruction and register list");1705 }1706 }1707 1708 if (const char *MatchDiag = getMatchKindDiag((RISCVMatchResultTy)Result)) {1709 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();1710 return Error(ErrorLoc, MatchDiag);1711 }1712 1713 llvm_unreachable("Unknown match type detected!");1714}1715 1716// Attempts to match Name as a register (either using the default name or1717// alternative ABI names), returning the matching register. Upon failure,1718// returns a non-valid MCRegister. If IsRVE, then registers x16-x31 will be1719// rejected.1720MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {1721 MCRegister Reg = MatchRegisterName(Name);1722 // The 16-/32-/128- and 64-bit FPRs have the same asm name. Check1723 // that the initial match always matches the 64-bit variant, and1724 // not the 16/32/128-bit one.1725 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));1726 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));1727 assert(!(Reg >= RISCV::F0_Q && Reg <= RISCV::F31_Q));1728 // The default FPR register class is based on the tablegen enum ordering.1729 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");1730 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");1731 static_assert(RISCV::F0_D < RISCV::F0_Q, "FPR matching must be updated");1732 if (!Reg)1733 Reg = MatchRegisterAltName(Name);1734 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)1735 Reg = MCRegister();1736 return Reg;1737}1738 1739bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,1740 SMLoc &EndLoc) {1741 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())1742 return Error(StartLoc, "invalid register name");1743 return false;1744}1745 1746ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,1747 SMLoc &EndLoc) {1748 const AsmToken &Tok = getParser().getTok();1749 StartLoc = Tok.getLoc();1750 EndLoc = Tok.getEndLoc();1751 StringRef Name = getLexer().getTok().getIdentifier();1752 1753 Reg = matchRegisterNameHelper(Name);1754 if (!Reg)1755 return ParseStatus::NoMatch;1756 1757 getParser().Lex(); // Eat identifier token.1758 return ParseStatus::Success;1759}1760 1761ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,1762 bool AllowParens) {1763 SMLoc FirstS = getLoc();1764 bool HadParens = false;1765 AsmToken LParen;1766 1767 // If this is an LParen and a parenthesised register name is allowed, parse it1768 // atomically.1769 if (AllowParens && getLexer().is(AsmToken::LParen)) {1770 AsmToken Buf[2];1771 size_t ReadCount = getLexer().peekTokens(Buf);1772 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {1773 HadParens = true;1774 LParen = getParser().getTok();1775 getParser().Lex(); // Eat '('1776 }1777 }1778 1779 switch (getLexer().getKind()) {1780 default:1781 if (HadParens)1782 getLexer().UnLex(LParen);1783 return ParseStatus::NoMatch;1784 case AsmToken::Identifier:1785 StringRef Name = getLexer().getTok().getIdentifier();1786 MCRegister Reg = matchRegisterNameHelper(Name);1787 1788 if (!Reg) {1789 if (HadParens)1790 getLexer().UnLex(LParen);1791 return ParseStatus::NoMatch;1792 }1793 if (HadParens)1794 Operands.push_back(RISCVOperand::createToken("(", FirstS));1795 SMLoc S = getLoc();1796 SMLoc E = getTok().getEndLoc();1797 getLexer().Lex();1798 Operands.push_back(RISCVOperand::createReg(Reg, S, E));1799 }1800 1801 if (HadParens) {1802 getParser().Lex(); // Eat ')'1803 Operands.push_back(RISCVOperand::createToken(")", getLoc()));1804 }1805 1806 return ParseStatus::Success;1807}1808 1809ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {1810 SMLoc S = getLoc();1811 SMLoc E;1812 const MCExpr *Res;1813 1814 switch (getLexer().getKind()) {1815 default:1816 return ParseStatus::NoMatch;1817 case AsmToken::LParen:1818 case AsmToken::Minus:1819 case AsmToken::Plus:1820 case AsmToken::Exclaim:1821 case AsmToken::Tilde:1822 case AsmToken::Integer:1823 case AsmToken::String: {1824 if (getParser().parseExpression(Res, E))1825 return ParseStatus::Failure;1826 1827 auto *CE = dyn_cast<MCConstantExpr>(Res);1828 if (CE) {1829 int64_t Imm = CE->getValue();1830 if (isUInt<7>(Imm)) {1831 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));1832 return ParseStatus::Success;1833 }1834 }1835 1836 break;1837 }1838 case AsmToken::Identifier: {1839 StringRef Identifier;1840 if (getParser().parseIdentifier(Identifier))1841 return ParseStatus::Failure;1842 1843 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);1844 if (Opcode) {1845 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&1846 "Unexpected opcode");1847 Res = MCConstantExpr::create(Opcode->Value, getContext());1848 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());1849 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));1850 return ParseStatus::Success;1851 }1852 1853 break;1854 }1855 case AsmToken::Percent:1856 break;1857 }1858 1859 return generateImmOutOfRangeError(1860 S, 0, 127,1861 "opcode must be a valid opcode name or an immediate in the range");1862}1863 1864ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {1865 SMLoc S = getLoc();1866 SMLoc E;1867 const MCExpr *Res;1868 1869 switch (getLexer().getKind()) {1870 default:1871 return ParseStatus::NoMatch;1872 case AsmToken::LParen:1873 case AsmToken::Minus:1874 case AsmToken::Plus:1875 case AsmToken::Exclaim:1876 case AsmToken::Tilde:1877 case AsmToken::Integer:1878 case AsmToken::String: {1879 if (getParser().parseExpression(Res, E))1880 return ParseStatus::Failure;1881 1882 auto *CE = dyn_cast<MCConstantExpr>(Res);1883 if (CE) {1884 int64_t Imm = CE->getValue();1885 if (Imm >= 0 && Imm <= 2) {1886 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));1887 return ParseStatus::Success;1888 }1889 }1890 1891 break;1892 }1893 case AsmToken::Identifier: {1894 StringRef Identifier;1895 if (getParser().parseIdentifier(Identifier))1896 return ParseStatus::Failure;1897 1898 unsigned Opcode;1899 if (Identifier == "C0")1900 Opcode = 0;1901 else if (Identifier == "C1")1902 Opcode = 1;1903 else if (Identifier == "C2")1904 Opcode = 2;1905 else1906 break;1907 1908 Res = MCConstantExpr::create(Opcode, getContext());1909 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());1910 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));1911 return ParseStatus::Success;1912 }1913 case AsmToken::Percent: {1914 // Discard operand with modifier.1915 break;1916 }1917 }1918 1919 return generateImmOutOfRangeError(1920 S, 0, 2,1921 "opcode must be a valid opcode name or an immediate in the range");1922}1923 1924ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {1925 SMLoc S = getLoc();1926 const MCExpr *Res;1927 1928 auto SysRegFromConstantInt = [this](const MCExpr *E, SMLoc S) {1929 if (auto *CE = dyn_cast<MCConstantExpr>(E)) {1930 int64_t Imm = CE->getValue();1931 if (isUInt<12>(Imm)) {1932 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);1933 // Accept an immediate representing a named Sys Reg if it satisfies the1934 // the required features.1935 for (auto &Reg : Range) {1936 if (Reg.IsAltName || Reg.IsDeprecatedName)1937 continue;1938 if (Reg.haveRequiredFeatures(STI->getFeatureBits()))1939 return RISCVOperand::createSysReg(Reg.Name, S, Imm);1940 }1941 // Accept an immediate representing an un-named Sys Reg if the range is1942 // valid, regardless of the required features.1943 return RISCVOperand::createSysReg("", S, Imm);1944 }1945 }1946 return std::unique_ptr<RISCVOperand>();1947 };1948 1949 switch (getLexer().getKind()) {1950 default:1951 return ParseStatus::NoMatch;1952 case AsmToken::LParen:1953 case AsmToken::Minus:1954 case AsmToken::Plus:1955 case AsmToken::Exclaim:1956 case AsmToken::Tilde:1957 case AsmToken::Integer:1958 case AsmToken::String: {1959 if (getParser().parseExpression(Res))1960 return ParseStatus::Failure;1961 1962 if (auto SysOpnd = SysRegFromConstantInt(Res, S)) {1963 Operands.push_back(std::move(SysOpnd));1964 return ParseStatus::Success;1965 }1966 1967 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);1968 }1969 case AsmToken::Identifier: {1970 StringRef Identifier;1971 if (getParser().parseIdentifier(Identifier))1972 return ParseStatus::Failure;1973 1974 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);1975 1976 if (SysReg) {1977 if (SysReg->IsDeprecatedName) {1978 // Lookup the undeprecated name.1979 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);1980 for (auto &Reg : Range) {1981 if (Reg.IsAltName || Reg.IsDeprecatedName)1982 continue;1983 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +1984 Reg.Name + "'");1985 }1986 }1987 1988 // Accept a named Sys Reg if the required features are present.1989 const auto &FeatureBits = getSTI().getFeatureBits();1990 if (!SysReg->haveRequiredFeatures(FeatureBits)) {1991 const auto *Feature = llvm::find_if(RISCVFeatureKV, [&](auto Feature) {1992 return SysReg->FeaturesRequired[Feature.Value];1993 });1994 auto ErrorMsg = std::string("system register '") + SysReg->Name + "' ";1995 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {1996 ErrorMsg += "is RV32 only";1997 if (Feature != std::end(RISCVFeatureKV))1998 ErrorMsg += " and ";1999 }2000 if (Feature != std::end(RISCVFeatureKV)) {2001 ErrorMsg +=2002 "requires '" + std::string(Feature->Key) + "' to be enabled";2003 }2004 2005 return Error(S, ErrorMsg);2006 }2007 Operands.push_back(2008 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));2009 return ParseStatus::Success;2010 }2011 2012 // Accept a symbol name that evaluates to an absolute value.2013 MCSymbol *Sym = getContext().lookupSymbol(Identifier);2014 if (Sym && Sym->isVariable()) {2015 // Pass false for SetUsed, since redefining the value later does not2016 // affect this instruction.2017 if (auto SysOpnd = SysRegFromConstantInt(Sym->getVariableValue(), S)) {2018 Operands.push_back(std::move(SysOpnd));2019 return ParseStatus::Success;2020 }2021 }2022 2023 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,2024 "operand must be a valid system register "2025 "name or an integer in the range");2026 }2027 case AsmToken::Percent: {2028 // Discard operand with modifier.2029 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);2030 }2031 }2032 2033 return ParseStatus::NoMatch;2034}2035 2036ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {2037 SMLoc S = getLoc();2038 2039 // Parse special floats (inf/nan/min) representation.2040 if (getTok().is(AsmToken::Identifier)) {2041 StringRef Identifier = getTok().getIdentifier();2042 if (Identifier.compare_insensitive("inf") == 0) {2043 Operands.push_back(2044 RISCVOperand::createExpr(MCConstantExpr::create(30, getContext()), S,2045 getTok().getEndLoc(), isRV64()));2046 } else if (Identifier.compare_insensitive("nan") == 0) {2047 Operands.push_back(2048 RISCVOperand::createExpr(MCConstantExpr::create(31, getContext()), S,2049 getTok().getEndLoc(), isRV64()));2050 } else if (Identifier.compare_insensitive("min") == 0) {2051 Operands.push_back(2052 RISCVOperand::createExpr(MCConstantExpr::create(1, getContext()), S,2053 getTok().getEndLoc(), isRV64()));2054 } else {2055 return TokError("invalid floating point literal");2056 }2057 2058 Lex(); // Eat the token.2059 2060 return ParseStatus::Success;2061 }2062 2063 // Handle negation, as that still comes through as a separate token.2064 bool IsNegative = parseOptionalToken(AsmToken::Minus);2065 2066 const AsmToken &Tok = getTok();2067 if (!Tok.is(AsmToken::Real))2068 return TokError("invalid floating point immediate");2069 2070 // Parse FP representation.2071 APFloat RealVal(APFloat::IEEEdouble());2072 auto StatusOrErr =2073 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);2074 if (errorToBool(StatusOrErr.takeError()))2075 return TokError("invalid floating point representation");2076 2077 if (IsNegative)2078 RealVal.changeSign();2079 2080 Operands.push_back(RISCVOperand::createFPImm(2081 RealVal.bitcastToAPInt().getZExtValue(), S));2082 2083 Lex(); // Eat the token.2084 2085 return ParseStatus::Success;2086}2087 2088ParseStatus RISCVAsmParser::parseExpression(OperandVector &Operands) {2089 SMLoc S = getLoc();2090 SMLoc E;2091 const MCExpr *Res;2092 2093 switch (getLexer().getKind()) {2094 default:2095 return ParseStatus::NoMatch;2096 case AsmToken::LParen:2097 case AsmToken::Dot:2098 case AsmToken::Minus:2099 case AsmToken::Plus:2100 case AsmToken::Exclaim:2101 case AsmToken::Tilde:2102 case AsmToken::Integer:2103 case AsmToken::String:2104 case AsmToken::Identifier:2105 if (getParser().parseExpression(Res, E))2106 return ParseStatus::Failure;2107 break;2108 case AsmToken::Percent:2109 return parseOperandWithSpecifier(Operands);2110 }2111 2112 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));2113 return ParseStatus::Success;2114}2115 2116ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {2117 SMLoc S = getLoc();2118 SMLoc E;2119 2120 if (parseToken(AsmToken::Percent, "expected '%' relocation specifier"))2121 return ParseStatus::Failure;2122 const MCExpr *Expr = nullptr;2123 bool Failed = parseExprWithSpecifier(Expr, E);2124 if (!Failed)2125 Operands.push_back(RISCVOperand::createExpr(Expr, S, E, isRV64()));2126 return Failed;2127}2128 2129bool RISCVAsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {2130 SMLoc Loc = getLoc();2131 if (getLexer().getKind() != AsmToken::Identifier)2132 return TokError("expected '%' relocation specifier");2133 StringRef Identifier = getParser().getTok().getIdentifier();2134 auto Spec = RISCV::parseSpecifierName(Identifier);2135 if (!Spec)2136 return TokError("invalid relocation specifier");2137 2138 getParser().Lex(); // Eat the identifier2139 if (parseToken(AsmToken::LParen, "expected '('"))2140 return true;2141 2142 const MCExpr *SubExpr;2143 if (getParser().parseParenExpression(SubExpr, E))2144 return true;2145 2146 Res = MCSpecifierExpr::create(SubExpr, Spec, getContext(), Loc);2147 return false;2148}2149 2150bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {2151 SMLoc E;2152 if (parseOptionalToken(AsmToken::Percent))2153 return parseExprWithSpecifier(Res, E);2154 return getParser().parseExpression(Res);2155}2156 2157ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {2158 SMLoc S = getLoc();2159 const MCExpr *Res;2160 2161 if (getLexer().getKind() != AsmToken::Identifier)2162 return ParseStatus::NoMatch;2163 2164 StringRef Identifier;2165 AsmToken Tok = getLexer().getTok();2166 2167 if (getParser().parseIdentifier(Identifier))2168 return ParseStatus::Failure;2169 2170 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());2171 2172 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);2173 2174 if (Sym->isVariable()) {2175 const MCExpr *V = Sym->getVariableValue();2176 if (!isa<MCSymbolRefExpr>(V)) {2177 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.2178 return ParseStatus::NoMatch;2179 }2180 Res = V;2181 } else2182 Res = MCSymbolRefExpr::create(Sym, getContext());2183 2184 MCBinaryExpr::Opcode Opcode;2185 switch (getLexer().getKind()) {2186 default:2187 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));2188 return ParseStatus::Success;2189 case AsmToken::Plus:2190 Opcode = MCBinaryExpr::Add;2191 getLexer().Lex();2192 break;2193 case AsmToken::Minus:2194 Opcode = MCBinaryExpr::Sub;2195 getLexer().Lex();2196 break;2197 }2198 2199 const MCExpr *Expr;2200 if (getParser().parseExpression(Expr, E))2201 return ParseStatus::Failure;2202 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());2203 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));2204 return ParseStatus::Success;2205}2206 2207ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {2208 SMLoc S = getLoc();2209 const MCExpr *Res;2210 2211 if (getLexer().getKind() != AsmToken::Identifier)2212 return ParseStatus::NoMatch;2213 std::string Identifier(getTok().getIdentifier());2214 2215 if (getLexer().peekTok().is(AsmToken::At)) {2216 Lex();2217 Lex();2218 StringRef PLT;2219 SMLoc Loc = getLoc();2220 if (getParser().parseIdentifier(PLT) || PLT != "plt")2221 return Error(Loc, "@ (except the deprecated/ignored @plt) is disallowed");2222 } else if (!getLexer().peekTok().is(AsmToken::EndOfStatement)) {2223 // Avoid parsing the register in `call rd, foo` as a call symbol.2224 return ParseStatus::NoMatch;2225 } else {2226 Lex();2227 }2228 2229 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());2230 RISCV::Specifier Kind = ELF::R_RISCV_CALL_PLT;2231 2232 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);2233 Res = MCSymbolRefExpr::create(Sym, getContext());2234 Res = MCSpecifierExpr::create(Res, Kind, getContext());2235 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));2236 return ParseStatus::Success;2237}2238 2239ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {2240 SMLoc S = getLoc();2241 SMLoc E;2242 const MCExpr *Res;2243 2244 if (getParser().parseExpression(Res, E))2245 return ParseStatus::Failure;2246 2247 if (Res->getKind() != MCExpr::ExprKind::SymbolRef)2248 return Error(S, "operand must be a valid jump target");2249 2250 Res = MCSpecifierExpr::create(Res, ELF::R_RISCV_CALL_PLT, getContext());2251 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));2252 return ParseStatus::Success;2253}2254 2255ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {2256 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`2257 // both being acceptable forms. When parsing `jal ra, foo` this function2258 // will be called for the `ra` register operand in an attempt to match the2259 // single-operand alias. parseJALOffset must fail for this case. It would2260 // seem logical to try parse the operand using parseExpression and return2261 // NoMatch if the next token is a comma (meaning we must be parsing a jal in2262 // the second form rather than the first). We can't do this as there's no2263 // way of rewinding the lexer state. Instead, return NoMatch if this operand2264 // is an identifier and is followed by a comma.2265 if (getLexer().is(AsmToken::Identifier) &&2266 getLexer().peekTok().is(AsmToken::Comma))2267 return ParseStatus::NoMatch;2268 2269 return parseExpression(Operands);2270}2271 2272bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,2273 unsigned &Sew, unsigned &Lmul,2274 bool &Fractional, bool &TailAgnostic,2275 bool &MaskAgnostic, bool &AltFmt) {2276 if (Tok.isNot(AsmToken::Identifier))2277 return true;2278 2279 StringRef Identifier = Tok.getIdentifier();2280 if (State < VTypeState::SeenSew && Identifier.consume_front("e")) {2281 if (Identifier.getAsInteger(10, Sew)) {2282 if (Identifier == "16alt") {2283 AltFmt = true;2284 Sew = 16;2285 } else if (Identifier == "8alt") {2286 AltFmt = true;2287 Sew = 8;2288 } else {2289 return true;2290 }2291 }2292 if (!RISCVVType::isValidSEW(Sew))2293 return true;2294 2295 State = VTypeState::SeenSew;2296 return false;2297 }2298 2299 if (State < VTypeState::SeenLmul && Identifier.consume_front("m")) {2300 // Might arrive here if lmul and tail policy unspecified, if so we're2301 // parsing a MaskPolicy not an LMUL.2302 if (Identifier == "a" || Identifier == "u") {2303 MaskAgnostic = (Identifier == "a");2304 State = VTypeState::SeenMaskPolicy;2305 return false;2306 }2307 2308 Fractional = Identifier.consume_front("f");2309 if (Identifier.getAsInteger(10, Lmul))2310 return true;2311 if (!RISCVVType::isValidLMUL(Lmul, Fractional))2312 return true;2313 2314 if (Fractional) {2315 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;2316 unsigned MinLMUL = ELEN / 8;2317 if (Lmul > MinLMUL)2318 Warning(Tok.getLoc(),2319 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +2320 Twine(MinLMUL) + " is reserved");2321 }2322 2323 State = VTypeState::SeenLmul;2324 return false;2325 }2326 2327 if (State < VTypeState::SeenTailPolicy && Identifier.starts_with("t")) {2328 if (Identifier == "ta")2329 TailAgnostic = true;2330 else if (Identifier == "tu")2331 TailAgnostic = false;2332 else2333 return true;2334 2335 State = VTypeState::SeenTailPolicy;2336 return false;2337 }2338 2339 if (State < VTypeState::SeenMaskPolicy && Identifier.starts_with("m")) {2340 if (Identifier == "ma")2341 MaskAgnostic = true;2342 else if (Identifier == "mu")2343 MaskAgnostic = false;2344 else2345 return true;2346 2347 State = VTypeState::SeenMaskPolicy;2348 return false;2349 }2350 2351 return true;2352}2353 2354ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {2355 SMLoc S = getLoc();2356 2357 // Default values2358 unsigned Sew = 8;2359 unsigned Lmul = 1;2360 bool Fractional = false;2361 bool TailAgnostic = false;2362 bool MaskAgnostic = false;2363 bool AltFmt = false;2364 2365 VTypeState State = VTypeState::SeenNothingYet;2366 do {2367 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,2368 MaskAgnostic, AltFmt)) {2369 // The first time, errors return NoMatch rather than Failure2370 if (State == VTypeState::SeenNothingYet)2371 return ParseStatus::NoMatch;2372 break;2373 }2374 2375 getLexer().Lex();2376 } while (parseOptionalToken(AsmToken::Comma));2377 2378 if (!getLexer().is(AsmToken::EndOfStatement) ||2379 State == VTypeState::SeenNothingYet)2380 return generateVTypeError(S);2381 2382 RISCVVType::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);2383 if (Fractional) {2384 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;2385 unsigned MaxSEW = ELEN / Lmul;2386 // If MaxSEW < 8, we should have printed warning about reserved LMUL.2387 if (MaxSEW >= 8 && Sew > MaxSEW)2388 Warning(S, "use of vtype encodings with SEW > " + Twine(MaxSEW) +2389 " and LMUL == mf" + Twine(Lmul) +2390 " may not be compatible with all RVV implementations");2391 }2392 2393 unsigned VTypeI =2394 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic, AltFmt);2395 Operands.push_back(RISCVOperand::createVType(VTypeI, S));2396 return ParseStatus::Success;2397}2398 2399bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {2400 if (STI->hasFeature(RISCV::FeatureStdExtZvfbfa) ||2401 STI->hasFeature(RISCV::FeatureVendorXSfvfbfexp16e))2402 return Error(2403 ErrorLoc,2404 "operand must be "2405 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");2406 return Error(2407 ErrorLoc,2408 "operand must be "2409 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");2410}2411 2412ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {2413 SMLoc S = getLoc();2414 2415 unsigned Widen = 0;2416 unsigned SEW = 0;2417 bool AltFmt = false;2418 StringRef Identifier;2419 2420 if (getTok().isNot(AsmToken::Identifier))2421 goto Fail;2422 2423 Identifier = getTok().getIdentifier();2424 2425 if (!Identifier.consume_front("e"))2426 goto Fail;2427 2428 if (Identifier.getAsInteger(10, SEW)) {2429 if (Identifier != "16alt")2430 goto Fail;2431 2432 AltFmt = true;2433 SEW = 16;2434 }2435 if (!RISCVVType::isValidSEW(SEW))2436 goto Fail;2437 2438 Lex();2439 2440 if (!parseOptionalToken(AsmToken::Comma))2441 goto Fail;2442 2443 if (getTok().isNot(AsmToken::Identifier))2444 goto Fail;2445 2446 Identifier = getTok().getIdentifier();2447 2448 if (!Identifier.consume_front("w"))2449 goto Fail;2450 if (Identifier.getAsInteger(10, Widen))2451 goto Fail;2452 if (Widen != 1 && Widen != 2 && Widen != 4)2453 goto Fail;2454 2455 Lex();2456 2457 if (getLexer().is(AsmToken::EndOfStatement)) {2458 Operands.push_back(RISCVOperand::createVType(2459 RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));2460 return ParseStatus::Success;2461 }2462 2463Fail:2464 return generateXSfmmVTypeError(S);2465}2466 2467bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {2468 return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");2469}2470 2471ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {2472 if (getLexer().isNot(AsmToken::Identifier))2473 return ParseStatus::NoMatch;2474 2475 StringRef Name = getLexer().getTok().getIdentifier();2476 if (!Name.consume_back(".t"))2477 return Error(getLoc(), "expected '.t' suffix");2478 MCRegister Reg = matchRegisterNameHelper(Name);2479 2480 if (!Reg)2481 return ParseStatus::NoMatch;2482 if (Reg != RISCV::V0)2483 return ParseStatus::NoMatch;2484 SMLoc S = getLoc();2485 SMLoc E = getTok().getEndLoc();2486 getLexer().Lex();2487 Operands.push_back(RISCVOperand::createReg(Reg, S, E));2488 return ParseStatus::Success;2489}2490 2491ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {2492 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))2493 return ParseStatus::NoMatch;2494 2495 return parseGPRAsFPR(Operands);2496}2497 2498ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {2499 if (getLexer().isNot(AsmToken::Identifier))2500 return ParseStatus::NoMatch;2501 2502 StringRef Name = getLexer().getTok().getIdentifier();2503 MCRegister Reg = matchRegisterNameHelper(Name);2504 2505 if (!Reg)2506 return ParseStatus::NoMatch;2507 SMLoc S = getLoc();2508 SMLoc E = getTok().getEndLoc();2509 getLexer().Lex();2510 Operands.push_back(RISCVOperand::createReg(2511 Reg, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));2512 return ParseStatus::Success;2513}2514 2515ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {2516 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))2517 return ParseStatus::NoMatch;2518 2519 if (getLexer().isNot(AsmToken::Identifier))2520 return ParseStatus::NoMatch;2521 2522 StringRef Name = getLexer().getTok().getIdentifier();2523 MCRegister Reg = matchRegisterNameHelper(Name);2524 2525 if (!Reg)2526 return ParseStatus::NoMatch;2527 2528 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))2529 return ParseStatus::NoMatch;2530 2531 if ((Reg - RISCV::X0) & 1) {2532 // Only report the even register error if we have at least Zfinx so we know2533 // some FP is enabled. We already checked F earlier.2534 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))2535 return TokError("double precision floating point operands must use even "2536 "numbered X register");2537 return ParseStatus::NoMatch;2538 }2539 2540 SMLoc S = getLoc();2541 SMLoc E = getTok().getEndLoc();2542 getLexer().Lex();2543 2544 const MCRegisterInfo *RI = getContext().getRegisterInfo();2545 MCRegister Pair = RI->getMatchingSuperReg(2546 Reg, RISCV::sub_gpr_even,2547 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);2548 Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));2549 return ParseStatus::Success;2550}2551 2552template <bool IsRV64>2553ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {2554 return parseGPRPair(Operands, IsRV64);2555}2556 2557ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,2558 bool IsRV64Inst) {2559 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on2560 // RV64 as it will prevent matching the RV64 version of the same instruction2561 // that doesn't use a GPRPair.2562 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can2563 // still parse as a pair.2564 if (!IsRV64Inst && isRV64())2565 return ParseStatus::NoMatch;2566 2567 if (getLexer().isNot(AsmToken::Identifier))2568 return ParseStatus::NoMatch;2569 2570 StringRef Name = getLexer().getTok().getIdentifier();2571 MCRegister Reg = matchRegisterNameHelper(Name);2572 2573 if (!Reg)2574 return ParseStatus::NoMatch;2575 2576 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))2577 return ParseStatus::NoMatch;2578 2579 if ((Reg - RISCV::X0) & 1)2580 return TokError("register must be even");2581 2582 SMLoc S = getLoc();2583 SMLoc E = getTok().getEndLoc();2584 getLexer().Lex();2585 2586 const MCRegisterInfo *RI = getContext().getRegisterInfo();2587 MCRegister Pair = RI->getMatchingSuperReg(2588 Reg, RISCV::sub_gpr_even,2589 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);2590 Operands.push_back(RISCVOperand::createReg(Pair, S, E));2591 return ParseStatus::Success;2592}2593 2594ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {2595 if (getLexer().isNot(AsmToken::Identifier))2596 return TokError(2597 "operand must be a valid floating point rounding mode mnemonic");2598 2599 StringRef Str = getLexer().getTok().getIdentifier();2600 RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);2601 2602 if (FRM == RISCVFPRndMode::Invalid)2603 return TokError(2604 "operand must be a valid floating point rounding mode mnemonic");2605 2606 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));2607 Lex(); // Eat identifier token.2608 return ParseStatus::Success;2609}2610 2611ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {2612 const AsmToken &Tok = getLexer().getTok();2613 2614 if (Tok.is(AsmToken::Integer)) {2615 if (Tok.getIntVal() != 0)2616 goto ParseFail;2617 2618 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));2619 Lex();2620 return ParseStatus::Success;2621 }2622 2623 if (Tok.is(AsmToken::Identifier)) {2624 StringRef Str = Tok.getIdentifier();2625 2626 // Letters must be unique, taken from 'iorw', and in ascending order. This2627 // holds as long as each individual character is one of 'iorw' and is2628 // greater than the previous character.2629 unsigned Imm = 0;2630 bool Valid = true;2631 char Prev = '\0';2632 for (char c : Str) {2633 switch (c) {2634 default:2635 Valid = false;2636 break;2637 case 'i':2638 Imm |= RISCVFenceField::I;2639 break;2640 case 'o':2641 Imm |= RISCVFenceField::O;2642 break;2643 case 'r':2644 Imm |= RISCVFenceField::R;2645 break;2646 case 'w':2647 Imm |= RISCVFenceField::W;2648 break;2649 }2650 2651 if (c <= Prev) {2652 Valid = false;2653 break;2654 }2655 Prev = c;2656 }2657 2658 if (!Valid)2659 goto ParseFail;2660 2661 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));2662 Lex();2663 return ParseStatus::Success;2664 }2665 2666ParseFail:2667 return TokError("operand must be formed of letters selected in-order from "2668 "'iorw' or be 0");2669}2670 2671ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {2672 if (parseToken(AsmToken::LParen, "expected '('"))2673 return ParseStatus::Failure;2674 Operands.push_back(RISCVOperand::createToken("(", getLoc()));2675 2676 if (!parseRegister(Operands).isSuccess())2677 return Error(getLoc(), "expected register");2678 2679 if (parseToken(AsmToken::RParen, "expected ')'"))2680 return ParseStatus::Failure;2681 Operands.push_back(RISCVOperand::createToken(")", getLoc()));2682 2683 return ParseStatus::Success;2684}2685 2686ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {2687 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"2688 // as one of their register operands, such as `(a0)`. This just denotes that2689 // the register (in this case `a0`) contains a memory address.2690 //2691 // Normally, we would be able to parse these by putting the parens into the2692 // instruction string. However, GNU as also accepts a zero-offset memory2693 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed2694 // with parseExpression followed by parseMemOpBaseReg, but these instructions2695 // do not accept an immediate operand, and we do not want to add a "dummy"2696 // operand that is silently dropped.2697 //2698 // Instead, we use this custom parser. This will: allow (and discard) an2699 // offset if it is zero; require (and discard) parentheses; and add only the2700 // parsed register operand to `Operands`.2701 //2702 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,2703 // which will only print the register surrounded by parentheses (which GNU as2704 // also uses as its canonical representation for these operands).2705 std::unique_ptr<RISCVOperand> OptionalImmOp;2706 2707 if (getLexer().isNot(AsmToken::LParen)) {2708 // Parse an Integer token. We do not accept arbitrary constant expressions2709 // in the offset field (because they may include parens, which complicates2710 // parsing a lot).2711 int64_t ImmVal;2712 SMLoc ImmStart = getLoc();2713 if (getParser().parseIntToken(ImmVal,2714 "expected '(' or optional integer offset"))2715 return ParseStatus::Failure;2716 2717 // Create a RISCVOperand for checking later (so the error messages are2718 // nicer), but we don't add it to Operands.2719 SMLoc ImmEnd = getLoc();2720 OptionalImmOp =2721 RISCVOperand::createExpr(MCConstantExpr::create(ImmVal, getContext()),2722 ImmStart, ImmEnd, isRV64());2723 }2724 2725 if (parseToken(AsmToken::LParen,2726 OptionalImmOp ? "expected '(' after optional integer offset"2727 : "expected '(' or optional integer offset"))2728 return ParseStatus::Failure;2729 2730 if (!parseRegister(Operands).isSuccess())2731 return Error(getLoc(), "expected register");2732 2733 if (parseToken(AsmToken::RParen, "expected ')'"))2734 return ParseStatus::Failure;2735 2736 // Deferred Handling of non-zero offsets. This makes the error messages nicer.2737 if (OptionalImmOp && !OptionalImmOp->isImmZero())2738 return Error(2739 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",2740 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));2741 2742 return ParseStatus::Success;2743}2744 2745ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {2746 // RR : a2(a1)2747 if (getLexer().getKind() != AsmToken::Identifier)2748 return ParseStatus::NoMatch;2749 2750 SMLoc S = getLoc();2751 StringRef OffsetRegName = getLexer().getTok().getIdentifier();2752 MCRegister OffsetReg = matchRegisterNameHelper(OffsetRegName);2753 if (!OffsetReg ||2754 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(OffsetReg))2755 return Error(getLoc(), "expected GPR register");2756 getLexer().Lex();2757 2758 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))2759 return ParseStatus::Failure;2760 2761 if (getLexer().getKind() != AsmToken::Identifier)2762 return Error(getLoc(), "expected GPR register");2763 2764 StringRef BaseRegName = getLexer().getTok().getIdentifier();2765 MCRegister BaseReg = matchRegisterNameHelper(BaseRegName);2766 if (!BaseReg ||2767 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(BaseReg))2768 return Error(getLoc(), "expected GPR register");2769 getLexer().Lex();2770 2771 if (parseToken(AsmToken::RParen, "expected ')'"))2772 return ParseStatus::Failure;2773 2774 Operands.push_back(RISCVOperand::createRegReg(BaseReg, OffsetReg, S));2775 2776 return ParseStatus::Success;2777}2778 2779// RegList: {ra [, s0[-sN]]}2780// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}2781 2782// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which2783// must include `fp`/`s0` in the list:2784// RegList: {ra, s0[-sN]}2785// XRegList: {x1, x8[-x9][, x18[-xN]]}2786ParseStatus RISCVAsmParser::parseRegList(OperandVector &Operands,2787 bool MustIncludeS0) {2788 if (getTok().isNot(AsmToken::LCurly))2789 return ParseStatus::NoMatch;2790 2791 SMLoc S = getLoc();2792 2793 Lex();2794 2795 bool UsesXRegs;2796 MCRegister RegEnd;2797 do {2798 if (getTok().isNot(AsmToken::Identifier))2799 return Error(getLoc(), "invalid register");2800 2801 StringRef RegName = getTok().getIdentifier();2802 MCRegister Reg = matchRegisterNameHelper(RegName);2803 if (!Reg)2804 return Error(getLoc(), "invalid register");2805 2806 if (!RegEnd) {2807 UsesXRegs = RegName[0] == 'x';2808 if (Reg != RISCV::X1)2809 return Error(getLoc(), "register list must start from 'ra' or 'x1'");2810 } else if (RegEnd == RISCV::X1) {2811 if (Reg != RISCV::X8 || (UsesXRegs != (RegName[0] == 'x')))2812 return Error(getLoc(), Twine("register must be '") +2813 (UsesXRegs ? "x8" : "s0") + "'");2814 } else if (RegEnd == RISCV::X9 && UsesXRegs) {2815 if (Reg != RISCV::X18 || (RegName[0] != 'x'))2816 return Error(getLoc(), "register must be 'x18'");2817 } else {2818 return Error(getLoc(), "too many register ranges");2819 }2820 2821 RegEnd = Reg;2822 2823 Lex();2824 2825 SMLoc MinusLoc = getLoc();2826 if (parseOptionalToken(AsmToken::Minus)) {2827 if (RegEnd == RISCV::X1)2828 return Error(MinusLoc, Twine("register '") + (UsesXRegs ? "x1" : "ra") +2829 "' cannot start a multiple register range");2830 2831 if (getTok().isNot(AsmToken::Identifier))2832 return Error(getLoc(), "invalid register");2833 2834 StringRef RegName = getTok().getIdentifier();2835 MCRegister Reg = matchRegisterNameHelper(RegName);2836 if (!Reg)2837 return Error(getLoc(), "invalid register");2838 2839 if (RegEnd == RISCV::X8) {2840 if ((Reg != RISCV::X9 &&2841 (UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||2842 (UsesXRegs != (RegName[0] == 'x'))) {2843 if (UsesXRegs)2844 return Error(getLoc(), "register must be 'x9'");2845 return Error(getLoc(), "register must be in the range 's1' to 's11'");2846 }2847 } else if (RegEnd == RISCV::X18) {2848 if (Reg < RISCV::X19 || Reg > RISCV::X27 || (RegName[0] != 'x'))2849 return Error(getLoc(),2850 "register must be in the range 'x19' to 'x27'");2851 } else2852 llvm_unreachable("unexpected register");2853 2854 RegEnd = Reg;2855 2856 Lex();2857 }2858 } while (parseOptionalToken(AsmToken::Comma));2859 2860 if (parseToken(AsmToken::RCurly, "expected ',' or '}'"))2861 return ParseStatus::Failure;2862 2863 if (RegEnd == RISCV::X26)2864 return Error(S, "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "2865 "x18-x26}' is not supported");2866 2867 auto Encode = RISCVZC::encodeRegList(RegEnd, isRVE());2868 assert(Encode != RISCVZC::INVALID_RLIST);2869 2870 if (MustIncludeS0 && Encode == RISCVZC::RA)2871 return Error(S, "register list must include 's0' or 'x8'");2872 2873 Operands.push_back(RISCVOperand::createRegList(Encode, S));2874 2875 return ParseStatus::Success;2876}2877 2878ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,2879 bool ExpectNegative) {2880 SMLoc S = getLoc();2881 bool Negative = parseOptionalToken(AsmToken::Minus);2882 2883 if (getTok().isNot(AsmToken::Integer))2884 return ParseStatus::NoMatch;2885 2886 int64_t StackAdjustment = getTok().getIntVal();2887 2888 auto *RegListOp = static_cast<RISCVOperand *>(Operands.back().get());2889 if (!RegListOp->isRegList())2890 return ParseStatus::NoMatch;2891 2892 unsigned RlistEncode = RegListOp->RegList.Encoding;2893 2894 assert(RlistEncode != RISCVZC::INVALID_RLIST);2895 unsigned StackAdjBase = RISCVZC::getStackAdjBase(RlistEncode, isRV64());2896 if (Negative != ExpectNegative || StackAdjustment % 16 != 0 ||2897 StackAdjustment < StackAdjBase || (StackAdjustment - StackAdjBase) > 48) {2898 int64_t Lower = StackAdjBase;2899 int64_t Upper = StackAdjBase + 48;2900 if (ExpectNegative) {2901 Lower = -Lower;2902 Upper = -Upper;2903 std::swap(Lower, Upper);2904 }2905 return generateImmOutOfRangeError(S, Lower, Upper,2906 "stack adjustment for register list must "2907 "be a multiple of 16 bytes in the range");2908 }2909 2910 unsigned StackAdj = (StackAdjustment - StackAdjBase);2911 Operands.push_back(RISCVOperand::createStackAdj(StackAdj, S));2912 Lex();2913 return ParseStatus::Success;2914}2915 2916/// Looks at a token type and creates the relevant operand from this2917/// information, adding to Operands. If operand was parsed, returns false, else2918/// true.2919bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {2920 // Check if the current operand has a custom associated parser, if so, try to2921 // custom parse the operand, or fallback to the general approach.2922 ParseStatus Result =2923 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);2924 if (Result.isSuccess())2925 return false;2926 if (Result.isFailure())2927 return true;2928 2929 // Attempt to parse token as a register.2930 if (parseRegister(Operands, true).isSuccess())2931 return false;2932 2933 // Attempt to parse token as an expression2934 if (parseExpression(Operands).isSuccess()) {2935 // Parse memory base register if present2936 if (getLexer().is(AsmToken::LParen))2937 return !parseMemOpBaseReg(Operands).isSuccess();2938 return false;2939 }2940 2941 // Finally we have exhausted all options and must declare defeat.2942 Error(getLoc(), "unknown operand");2943 return true;2944}2945 2946bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,2947 StringRef Name, SMLoc NameLoc,2948 OperandVector &Operands) {2949 // Apply mnemonic aliases because the destination mnemonic may have require2950 // custom operand parsing. The generic tblgen'erated code does this later, at2951 // the start of MatchInstructionImpl(), but that's too late for custom2952 // operand parsing.2953 const FeatureBitset &AvailableFeatures = getAvailableFeatures();2954 applyMnemonicAliases(Name, AvailableFeatures, 0);2955 2956 // First operand is token for instruction2957 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));2958 2959 // If there are no more operands, then finish2960 if (getLexer().is(AsmToken::EndOfStatement)) {2961 getParser().Lex(); // Consume the EndOfStatement.2962 return false;2963 }2964 2965 // Parse first operand2966 if (parseOperand(Operands, Name))2967 return true;2968 2969 // Parse until end of statement, consuming commas between operands2970 while (parseOptionalToken(AsmToken::Comma)) {2971 // Parse next operand2972 if (parseOperand(Operands, Name))2973 return true;2974 }2975 2976 if (getParser().parseEOL("unexpected token")) {2977 getParser().eatToEndOfStatement();2978 return true;2979 }2980 return false;2981}2982 2983bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,2984 RISCV::Specifier &Kind) {2985 Kind = RISCV::S_None;2986 if (const auto *RE = dyn_cast<MCSpecifierExpr>(Expr)) {2987 Kind = RE->getSpecifier();2988 Expr = RE->getSubExpr();2989 }2990 2991 MCValue Res;2992 if (Expr->evaluateAsRelocatable(Res, nullptr))2993 return Res.getSpecifier() == RISCV::S_None;2994 return false;2995}2996 2997bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {2998 MCValue Res;2999 if (Expr->evaluateAsRelocatable(Res, nullptr)) {3000 return Res.getSpecifier() == RISCV::S_None && Res.getAddSym() &&3001 Res.getSubSym();3002 }3003 return false;3004}3005 3006ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {3007 StringRef IDVal = DirectiveID.getString();3008 3009 if (IDVal == ".option")3010 return parseDirectiveOption();3011 if (IDVal == ".attribute")3012 return parseDirectiveAttribute();3013 if (IDVal == ".insn")3014 return parseDirectiveInsn(DirectiveID.getLoc());3015 if (IDVal == ".variant_cc")3016 return parseDirectiveVariantCC();3017 3018 return ParseStatus::NoMatch;3019}3020 3021bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,3022 bool FromOptionDirective) {3023 for (auto &Feature : RISCVFeatureKV)3024 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))3025 clearFeatureBits(Feature.Value, Feature.Key);3026 3027 auto ParseResult = llvm::RISCVISAInfo::parseArchString(3028 Arch, /*EnableExperimentalExtension=*/true,3029 /*ExperimentalExtensionVersionCheck=*/true);3030 if (!ParseResult) {3031 std::string Buffer;3032 raw_string_ostream OutputErrMsg(Buffer);3033 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {3034 OutputErrMsg << "invalid arch name '" << Arch << "', "3035 << ErrMsg.getMessage();3036 });3037 3038 return Error(Loc, OutputErrMsg.str());3039 }3040 auto &ISAInfo = *ParseResult;3041 3042 for (auto &Feature : RISCVFeatureKV)3043 if (ISAInfo->hasExtension(Feature.Key))3044 setFeatureBits(Feature.Value, Feature.Key);3045 3046 if (FromOptionDirective) {3047 if (ISAInfo->getXLen() == 32 && isRV64())3048 return Error(Loc, "bad arch string switching from rv64 to rv32");3049 else if (ISAInfo->getXLen() == 64 && !isRV64())3050 return Error(Loc, "bad arch string switching from rv32 to rv64");3051 }3052 3053 if (ISAInfo->getXLen() == 32)3054 clearFeatureBits(RISCV::Feature64Bit, "64bit");3055 else if (ISAInfo->getXLen() == 64)3056 setFeatureBits(RISCV::Feature64Bit, "64bit");3057 else3058 return Error(Loc, "bad arch string " + Arch);3059 3060 Result = ISAInfo->toString();3061 return false;3062}3063 3064bool RISCVAsmParser::parseDirectiveOption() {3065 MCAsmParser &Parser = getParser();3066 // Get the option token.3067 AsmToken Tok = Parser.getTok();3068 3069 // At the moment only identifiers are supported.3070 if (parseToken(AsmToken::Identifier, "expected identifier"))3071 return true;3072 3073 StringRef Option = Tok.getIdentifier();3074 3075 if (Option == "push") {3076 if (Parser.parseEOL())3077 return true;3078 3079 getTargetStreamer().emitDirectiveOptionPush();3080 pushFeatureBits();3081 return false;3082 }3083 3084 if (Option == "pop") {3085 SMLoc StartLoc = Parser.getTok().getLoc();3086 if (Parser.parseEOL())3087 return true;3088 3089 getTargetStreamer().emitDirectiveOptionPop();3090 if (popFeatureBits())3091 return Error(StartLoc, ".option pop with no .option push");3092 3093 return false;3094 }3095 3096 if (Option == "arch") {3097 SmallVector<RISCVOptionArchArg> Args;3098 do {3099 if (Parser.parseComma())3100 return true;3101 3102 RISCVOptionArchArgType Type;3103 if (parseOptionalToken(AsmToken::Plus))3104 Type = RISCVOptionArchArgType::Plus;3105 else if (parseOptionalToken(AsmToken::Minus))3106 Type = RISCVOptionArchArgType::Minus;3107 else if (!Args.empty())3108 return Error(Parser.getTok().getLoc(),3109 "unexpected token, expected + or -");3110 else3111 Type = RISCVOptionArchArgType::Full;3112 3113 if (Parser.getTok().isNot(AsmToken::Identifier))3114 return Error(Parser.getTok().getLoc(),3115 "unexpected token, expected identifier");3116 3117 StringRef Arch = Parser.getTok().getString();3118 SMLoc Loc = Parser.getTok().getLoc();3119 Parser.Lex();3120 3121 if (Type == RISCVOptionArchArgType::Full) {3122 std::string Result;3123 if (resetToArch(Arch, Loc, Result, true))3124 return true;3125 3126 Args.emplace_back(Type, Result);3127 break;3128 }3129 3130 if (isDigit(Arch.back()))3131 return Error(3132 Loc, "extension version number parsing not currently implemented");3133 3134 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);3135 if (!enableExperimentalExtension() &&3136 StringRef(Feature).starts_with("experimental-"))3137 return Error(Loc, "unexpected experimental extensions");3138 auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);3139 if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)3140 return Error(Loc, "unknown extension feature");3141 3142 Args.emplace_back(Type, Arch.str());3143 3144 if (Type == RISCVOptionArchArgType::Plus) {3145 FeatureBitset OldFeatureBits = STI->getFeatureBits();3146 3147 setFeatureBits(Ext->Value, Ext->Key);3148 auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());3149 if (!ParseResult) {3150 copySTI().setFeatureBits(OldFeatureBits);3151 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));3152 3153 std::string Buffer;3154 raw_string_ostream OutputErrMsg(Buffer);3155 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {3156 OutputErrMsg << ErrMsg.getMessage();3157 });3158 3159 return Error(Loc, OutputErrMsg.str());3160 }3161 } else {3162 assert(Type == RISCVOptionArchArgType::Minus);3163 // It is invalid to disable an extension that there are other enabled3164 // extensions depend on it.3165 // TODO: Make use of RISCVISAInfo to handle this3166 for (auto &Feature : RISCVFeatureKV) {3167 if (getSTI().hasFeature(Feature.Value) &&3168 Feature.Implies.test(Ext->Value))3169 return Error(Loc, Twine("can't disable ") + Ext->Key +3170 " extension; " + Feature.Key +3171 " extension requires " + Ext->Key +3172 " extension");3173 }3174 3175 clearFeatureBits(Ext->Value, Ext->Key);3176 }3177 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));3178 3179 if (Parser.parseEOL())3180 return true;3181 3182 getTargetStreamer().emitDirectiveOptionArch(Args);3183 return false;3184 }3185 3186 if (Option == "exact") {3187 if (Parser.parseEOL())3188 return true;3189 3190 getTargetStreamer().emitDirectiveOptionExact();3191 setFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");3192 clearFeatureBits(RISCV::FeatureRelax, "relax");3193 return false;3194 }3195 3196 if (Option == "noexact") {3197 if (Parser.parseEOL())3198 return true;3199 3200 getTargetStreamer().emitDirectiveOptionNoExact();3201 clearFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");3202 setFeatureBits(RISCV::FeatureRelax, "relax");3203 return false;3204 }3205 3206 if (Option == "rvc") {3207 if (Parser.parseEOL())3208 return true;3209 3210 getTargetStreamer().emitDirectiveOptionRVC();3211 setFeatureBits(RISCV::FeatureStdExtC, "c");3212 return false;3213 }3214 3215 if (Option == "norvc") {3216 if (Parser.parseEOL())3217 return true;3218 3219 getTargetStreamer().emitDirectiveOptionNoRVC();3220 clearFeatureBits(RISCV::FeatureStdExtC, "c");3221 clearFeatureBits(RISCV::FeatureStdExtZca, "zca");3222 return false;3223 }3224 3225 if (Option == "pic") {3226 if (Parser.parseEOL())3227 return true;3228 3229 getTargetStreamer().emitDirectiveOptionPIC();3230 ParserOptions.IsPicEnabled = true;3231 return false;3232 }3233 3234 if (Option == "nopic") {3235 if (Parser.parseEOL())3236 return true;3237 3238 getTargetStreamer().emitDirectiveOptionNoPIC();3239 ParserOptions.IsPicEnabled = false;3240 return false;3241 }3242 3243 if (Option == "relax") {3244 if (Parser.parseEOL())3245 return true;3246 3247 getTargetStreamer().emitDirectiveOptionRelax();3248 setFeatureBits(RISCV::FeatureRelax, "relax");3249 return false;3250 }3251 3252 if (Option == "norelax") {3253 if (Parser.parseEOL())3254 return true;3255 3256 getTargetStreamer().emitDirectiveOptionNoRelax();3257 clearFeatureBits(RISCV::FeatureRelax, "relax");3258 return false;3259 }3260 3261 // Unknown option.3262 Warning(Parser.getTok().getLoc(),3263 "unknown option, expected 'push', 'pop', "3264 "'rvc', 'norvc', 'arch', 'relax', 'norelax', "3265 "'exact', or 'noexact'");3266 Parser.eatToEndOfStatement();3267 return false;3268}3269 3270/// parseDirectiveAttribute3271/// ::= .attribute expression ',' ( expression | "string" )3272/// ::= .attribute identifier ',' ( expression | "string" )3273bool RISCVAsmParser::parseDirectiveAttribute() {3274 MCAsmParser &Parser = getParser();3275 int64_t Tag;3276 SMLoc TagLoc;3277 TagLoc = Parser.getTok().getLoc();3278 if (Parser.getTok().is(AsmToken::Identifier)) {3279 StringRef Name = Parser.getTok().getIdentifier();3280 std::optional<unsigned> Ret =3281 ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());3282 if (!Ret)3283 return Error(TagLoc, "attribute name not recognised: " + Name);3284 Tag = *Ret;3285 Parser.Lex();3286 } else {3287 const MCExpr *AttrExpr;3288 3289 TagLoc = Parser.getTok().getLoc();3290 if (Parser.parseExpression(AttrExpr))3291 return true;3292 3293 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);3294 if (check(!CE, TagLoc, "expected numeric constant"))3295 return true;3296 3297 Tag = CE->getValue();3298 }3299 3300 if (Parser.parseComma())3301 return true;3302 3303 StringRef StringValue;3304 int64_t IntegerValue = 0;3305 bool IsIntegerValue = true;3306 3307 // RISC-V attributes have a string value if the tag number is odd3308 // and an integer value if the tag number is even.3309 if (Tag % 2)3310 IsIntegerValue = false;3311 3312 SMLoc ValueExprLoc = Parser.getTok().getLoc();3313 if (IsIntegerValue) {3314 const MCExpr *ValueExpr;3315 if (Parser.parseExpression(ValueExpr))3316 return true;3317 3318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);3319 if (!CE)3320 return Error(ValueExprLoc, "expected numeric constant");3321 IntegerValue = CE->getValue();3322 } else {3323 if (Parser.getTok().isNot(AsmToken::String))3324 return Error(Parser.getTok().getLoc(), "expected string constant");3325 3326 StringValue = Parser.getTok().getStringContents();3327 Parser.Lex();3328 }3329 3330 if (Parser.parseEOL())3331 return true;3332 3333 if (IsIntegerValue)3334 getTargetStreamer().emitAttribute(Tag, IntegerValue);3335 else if (Tag != RISCVAttrs::ARCH)3336 getTargetStreamer().emitTextAttribute(Tag, StringValue);3337 else {3338 std::string Result;3339 if (resetToArch(StringValue, ValueExprLoc, Result, false))3340 return true;3341 3342 // Then emit the arch string.3343 getTargetStreamer().emitTextAttribute(Tag, Result);3344 }3345 3346 return false;3347}3348 3349bool isValidInsnFormat(StringRef Format, const MCSubtargetInfo &STI) {3350 return StringSwitch<bool>(Format)3351 .Cases({"r", "r4", "i", "b", "sb", "u", "j", "uj", "s"}, true)3352 .Cases({"cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj"},3353 STI.hasFeature(RISCV::FeatureStdExtZca))3354 .Cases({"qc.eai", "qc.ei", "qc.eb", "qc.ej", "qc.es"},3355 !STI.hasFeature(RISCV::Feature64Bit))3356 .Default(false);3357}3358 3359/// parseDirectiveInsn3360/// ::= .insn [ format encoding, (operands (, operands)*) ]3361/// ::= .insn [ length, value ]3362/// ::= .insn [ value ]3363bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {3364 MCAsmParser &Parser = getParser();3365 3366 // Expect instruction format as identifier.3367 StringRef Format;3368 SMLoc ErrorLoc = Parser.getTok().getLoc();3369 if (Parser.parseIdentifier(Format)) {3370 // Try parsing .insn [ length , ] value3371 std::optional<int64_t> Length;3372 int64_t Value = 0;3373 if (Parser.parseAbsoluteExpression(Value))3374 return true;3375 if (Parser.parseOptionalToken(AsmToken::Comma)) {3376 Length = Value;3377 if (Parser.parseAbsoluteExpression(Value))3378 return true;3379 3380 if (*Length == 0 || (*Length % 2) != 0)3381 return Error(ErrorLoc,3382 "instruction lengths must be a non-zero multiple of two");3383 3384 // TODO: Support Instructions > 64 bits.3385 if (*Length > 8)3386 return Error(ErrorLoc,3387 "instruction lengths over 64 bits are not supported");3388 }3389 3390 // We only derive a length from the encoding for 16- and 32-bit3391 // instructions, as the encodings for longer instructions are not frozen in3392 // the spec.3393 int64_t EncodingDerivedLength = ((Value & 0b11) == 0b11) ? 4 : 2;3394 3395 if (Length) {3396 // Only check the length against the encoding if the length is present and3397 // could match3398 if ((*Length <= 4) && (*Length != EncodingDerivedLength))3399 return Error(ErrorLoc,3400 "instruction length does not match the encoding");3401 3402 if (!isUIntN(*Length * 8, Value))3403 return Error(ErrorLoc, "encoding value does not fit into instruction");3404 } else {3405 if (!isUIntN(EncodingDerivedLength * 8, Value))3406 return Error(ErrorLoc, "encoding value does not fit into instruction");3407 }3408 3409 if (!getSTI().hasFeature(RISCV::FeatureStdExtZca) &&3410 (EncodingDerivedLength == 2))3411 return Error(ErrorLoc, "compressed instructions are not allowed");3412 3413 if (getParser().parseEOL("invalid operand for instruction")) {3414 getParser().eatToEndOfStatement();3415 return true;3416 }3417 3418 unsigned Opcode;3419 if (Length) {3420 switch (*Length) {3421 case 2:3422 Opcode = RISCV::Insn16;3423 break;3424 case 4:3425 Opcode = RISCV::Insn32;3426 break;3427 case 6:3428 Opcode = RISCV::Insn48;3429 break;3430 case 8:3431 Opcode = RISCV::Insn64;3432 break;3433 default:3434 llvm_unreachable("Error should have already been emitted");3435 }3436 } else3437 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;3438 3439 emitToStreamer(getStreamer(), MCInstBuilder(Opcode).addImm(Value));3440 return false;3441 }3442 3443 if (!isValidInsnFormat(Format, getSTI()))3444 return Error(ErrorLoc, "invalid instruction format");3445 3446 std::string FormatName = (".insn_" + Format).str();3447 3448 ParseInstructionInfo Info;3449 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;3450 3451 if (parseInstruction(Info, FormatName, L, Operands))3452 return true;3453 3454 unsigned Opcode;3455 uint64_t ErrorInfo;3456 return matchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),3457 ErrorInfo,3458 /*MatchingInlineAsm=*/false);3459}3460 3461/// parseDirectiveVariantCC3462/// ::= .variant_cc symbol3463bool RISCVAsmParser::parseDirectiveVariantCC() {3464 StringRef Name;3465 if (getParser().parseIdentifier(Name))3466 return TokError("expected symbol name");3467 if (parseEOL())3468 return true;3469 getTargetStreamer().emitDirectiveVariantCC(3470 *getContext().getOrCreateSymbol(Name));3471 return false;3472}3473 3474void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {3475 MCInst CInst;3476 bool Res = false;3477 const MCSubtargetInfo &STI = getSTI();3478 if (!STI.hasFeature(RISCV::FeatureExactAssembly))3479 Res = RISCVRVC::compress(CInst, Inst, STI);3480 if (Res)3481 ++RISCVNumInstrsCompressed;3482 S.emitInstruction((Res ? CInst : Inst), STI);3483}3484 3485void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,3486 MCStreamer &Out) {3487 SmallVector<MCInst, 8> Seq;3488 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);3489 3490 for (MCInst &Inst : Seq) {3491 emitToStreamer(Out, Inst);3492 }3493}3494 3495void RISCVAsmParser::emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,3496 const MCExpr *Symbol,3497 RISCV::Specifier VKHi,3498 unsigned SecondOpcode, SMLoc IDLoc,3499 MCStreamer &Out) {3500 // A pair of instructions for PC-relative addressing; expands to3501 // TmpLabel: AUIPC TmpReg, VKHi(symbol)3502 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)3503 MCContext &Ctx = getContext();3504 3505 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");3506 Out.emitLabel(TmpLabel);3507 3508 const auto *SymbolHi = MCSpecifierExpr::create(Symbol, VKHi, Ctx);3509 emitToStreamer(Out,3510 MCInstBuilder(RISCV::AUIPC).addReg(TmpReg).addExpr(SymbolHi));3511 3512 const MCExpr *RefToLinkTmpLabel = MCSpecifierExpr::create(3513 MCSymbolRefExpr::create(TmpLabel, Ctx), RISCV::S_PCREL_LO, Ctx);3514 3515 emitToStreamer(Out, MCInstBuilder(SecondOpcode)3516 .addReg(DestReg)3517 .addReg(TmpReg)3518 .addExpr(RefToLinkTmpLabel));3519}3520 3521void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,3522 MCStreamer &Out) {3523 // The load local address pseudo-instruction "lla" is used in PC-relative3524 // addressing of local symbols:3525 // lla rdest, symbol3526 // expands to3527 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)3528 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)3529 MCRegister DestReg = Inst.getOperand(0).getReg();3530 const MCExpr *Symbol = Inst.getOperand(1).getExpr();3531 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_PCREL_HI20,3532 RISCV::ADDI, IDLoc, Out);3533}3534 3535void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,3536 MCStreamer &Out) {3537 // The load global address pseudo-instruction "lga" is used in GOT-indirect3538 // addressing of global symbols:3539 // lga rdest, symbol3540 // expands to3541 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)3542 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)3543 MCRegister DestReg = Inst.getOperand(0).getReg();3544 const MCExpr *Symbol = Inst.getOperand(1).getExpr();3545 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;3546 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_GOT_HI20,3547 SecondOpcode, IDLoc, Out);3548}3549 3550void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,3551 MCStreamer &Out) {3552 // The load address pseudo-instruction "la" is used in PC-relative and3553 // GOT-indirect addressing of global symbols:3554 // la rdest, symbol3555 // is an alias for either (for non-PIC)3556 // lla rdest, symbol3557 // or (for PIC)3558 // lga rdest, symbol3559 if (ParserOptions.IsPicEnabled)3560 emitLoadGlobalAddress(Inst, IDLoc, Out);3561 else3562 emitLoadLocalAddress(Inst, IDLoc, Out);3563}3564 3565void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,3566 MCStreamer &Out) {3567 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in3568 // initial-exec TLS model addressing of global symbols:3569 // la.tls.ie rdest, symbol3570 // expands to3571 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)3572 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)3573 MCRegister DestReg = Inst.getOperand(0).getReg();3574 const MCExpr *Symbol = Inst.getOperand(1).getExpr();3575 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;3576 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GOT_HI20,3577 SecondOpcode, IDLoc, Out);3578}3579 3580void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,3581 MCStreamer &Out) {3582 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in3583 // global-dynamic TLS model addressing of global symbols:3584 // la.tls.gd rdest, symbol3585 // expands to3586 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)3587 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)3588 MCRegister DestReg = Inst.getOperand(0).getReg();3589 const MCExpr *Symbol = Inst.getOperand(1).getExpr();3590 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GD_HI20,3591 RISCV::ADDI, IDLoc, Out);3592}3593 3594void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,3595 SMLoc IDLoc, MCStreamer &Out,3596 bool HasTmpReg) {3597 // The load/store pseudo-instruction does a pc-relative load with3598 // a symbol.3599 //3600 // The expansion looks like this3601 //3602 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)3603 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)3604 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;3605 MCRegister DestReg = Inst.getOperand(DestRegOpIdx).getReg();3606 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;3607 MCRegister TmpReg = Inst.getOperand(0).getReg();3608 3609 // If TmpReg is a GPR pair, get the even register.3610 if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(TmpReg)) {3611 const MCRegisterInfo *RI = getContext().getRegisterInfo();3612 TmpReg = RI->getSubReg(TmpReg, RISCV::sub_gpr_even);3613 }3614 3615 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();3616 emitAuipcInstPair(DestReg, TmpReg, Symbol, ELF::R_RISCV_PCREL_HI20, Opcode,3617 IDLoc, Out);3618}3619 3620void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,3621 int64_t Width, SMLoc IDLoc,3622 MCStreamer &Out) {3623 // The sign/zero extend pseudo-instruction does two shifts, with the shift3624 // amounts dependent on the XLEN.3625 //3626 // The expansion looks like this3627 //3628 // SLLI rd, rs, XLEN - Width3629 // SR[A|R]I rd, rd, XLEN - Width3630 const MCOperand &DestReg = Inst.getOperand(0);3631 const MCOperand &SourceReg = Inst.getOperand(1);3632 3633 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;3634 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;3635 3636 assert(ShAmt > 0 && "Shift amount must be non-zero.");3637 3638 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)3639 .addOperand(DestReg)3640 .addOperand(SourceReg)3641 .addImm(ShAmt));3642 3643 emitToStreamer(Out, MCInstBuilder(SecondOpcode)3644 .addOperand(DestReg)3645 .addOperand(DestReg)3646 .addImm(ShAmt));3647}3648 3649void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,3650 MCStreamer &Out) {3651 if (Inst.getNumOperands() == 3) {3652 // unmasked va >= x3653 //3654 // pseudoinstruction: vmsge{u}.vx vd, va, x3655 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd3656 emitToStreamer(Out, MCInstBuilder(Opcode)3657 .addOperand(Inst.getOperand(0))3658 .addOperand(Inst.getOperand(1))3659 .addOperand(Inst.getOperand(2))3660 .addReg(MCRegister())3661 .setLoc(IDLoc));3662 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)3663 .addOperand(Inst.getOperand(0))3664 .addOperand(Inst.getOperand(0))3665 .addOperand(Inst.getOperand(0))3666 .setLoc(IDLoc));3667 } else if (Inst.getNumOperands() == 4) {3668 // masked va >= x, vd != v03669 //3670 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t3671 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v03672 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&3673 "The destination register should not be V0.");3674 emitToStreamer(Out, MCInstBuilder(Opcode)3675 .addOperand(Inst.getOperand(0))3676 .addOperand(Inst.getOperand(1))3677 .addOperand(Inst.getOperand(2))3678 .addOperand(Inst.getOperand(3))3679 .setLoc(IDLoc));3680 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)3681 .addOperand(Inst.getOperand(0))3682 .addOperand(Inst.getOperand(0))3683 .addReg(RISCV::V0)3684 .setLoc(IDLoc));3685 } else if (Inst.getNumOperands() == 5 &&3686 Inst.getOperand(0).getReg() == RISCV::V0) {3687 // masked va >= x, vd == v03688 //3689 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt3690 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt3691 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&3692 "The destination register should be V0.");3693 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&3694 "The temporary vector register should not be V0.");3695 emitToStreamer(Out, MCInstBuilder(Opcode)3696 .addOperand(Inst.getOperand(1))3697 .addOperand(Inst.getOperand(2))3698 .addOperand(Inst.getOperand(3))3699 .addReg(MCRegister())3700 .setLoc(IDLoc));3701 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)3702 .addOperand(Inst.getOperand(0))3703 .addOperand(Inst.getOperand(0))3704 .addOperand(Inst.getOperand(1))3705 .setLoc(IDLoc));3706 } else if (Inst.getNumOperands() == 5) {3707 // masked va >= x, any vd3708 //3709 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt3710 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;3711 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd3712 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&3713 "The temporary vector register should not be V0.");3714 emitToStreamer(Out, MCInstBuilder(Opcode)3715 .addOperand(Inst.getOperand(1))3716 .addOperand(Inst.getOperand(2))3717 .addOperand(Inst.getOperand(3))3718 .addReg(MCRegister())3719 .setLoc(IDLoc));3720 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)3721 .addOperand(Inst.getOperand(1))3722 .addReg(RISCV::V0)3723 .addOperand(Inst.getOperand(1))3724 .setLoc(IDLoc));3725 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)3726 .addOperand(Inst.getOperand(0))3727 .addOperand(Inst.getOperand(0))3728 .addReg(RISCV::V0)3729 .setLoc(IDLoc));3730 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)3731 .addOperand(Inst.getOperand(0))3732 .addOperand(Inst.getOperand(1))3733 .addOperand(Inst.getOperand(0))3734 .setLoc(IDLoc));3735 }3736}3737 3738bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,3739 OperandVector &Operands) {3740 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");3741 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");3742 if (Inst.getOperand(2).getReg() != RISCV::X4) {3743 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();3744 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "3745 "%tprel_add specifier");3746 }3747 3748 return false;3749}3750 3751bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,3752 OperandVector &Operands) {3753 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");3754 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");3755 if (Inst.getOperand(0).getReg() != RISCV::X5) {3756 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();3757 return Error(ErrorLoc, "the output operand must be t0/x5 when using "3758 "%tlsdesc_call specifier");3759 }3760 3761 return false;3762}3763 3764std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {3765 return RISCVOperand::createReg(MCRegister(), llvm::SMLoc(), llvm::SMLoc());3766}3767 3768std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {3769 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,3770 llvm::SMLoc());3771}3772 3773std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {3774 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,3775 llvm::SMLoc());3776}3777 3778bool RISCVAsmParser::validateInstruction(MCInst &Inst,3779 OperandVector &Operands) {3780 unsigned Opcode = Inst.getOpcode();3781 3782 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||3783 Opcode == RISCV::PseudoVMSGE_VX_M_T) {3784 MCRegister DestReg = Inst.getOperand(0).getReg();3785 MCRegister TempReg = Inst.getOperand(1).getReg();3786 if (DestReg == TempReg) {3787 SMLoc Loc = Operands.back()->getStartLoc();3788 return Error(Loc, "the temporary vector register cannot be the same as "3789 "the destination register");3790 }3791 }3792 3793 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||3794 Opcode == RISCV::TH_LWD) {3795 MCRegister Rd1 = Inst.getOperand(0).getReg();3796 MCRegister Rd2 = Inst.getOperand(1).getReg();3797 MCRegister Rs1 = Inst.getOperand(2).getReg();3798 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.3799 if (Rs1 == Rd1 || Rs1 == Rd2 || Rd1 == Rd2) {3800 SMLoc Loc = Operands[1]->getStartLoc();3801 return Error(Loc, "rs1, rd1, and rd2 cannot overlap");3802 }3803 }3804 3805 if (Opcode == RISCV::CM_MVSA01 || Opcode == RISCV::QC_CM_MVSA01) {3806 MCRegister Rd1 = Inst.getOperand(0).getReg();3807 MCRegister Rd2 = Inst.getOperand(1).getReg();3808 if (Rd1 == Rd2) {3809 SMLoc Loc = Operands[1]->getStartLoc();3810 return Error(Loc, "rs1 and rs2 must be different");3811 }3812 }3813 3814 const MCInstrDesc &MCID = MII.get(Opcode);3815 if (!(MCID.TSFlags & RISCVII::ConstraintMask))3816 return false;3817 3818 if (Opcode == RISCV::SF_VC_V_XVW || Opcode == RISCV::SF_VC_V_IVW ||3819 Opcode == RISCV::SF_VC_V_FVW || Opcode == RISCV::SF_VC_V_VVW) {3820 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for SF_VC_V_XVW.3821 MCRegister VCIXDst = Inst.getOperand(0).getReg();3822 SMLoc VCIXDstLoc = Operands[2]->getStartLoc();3823 if (MCID.TSFlags & RISCVII::VS1Constraint) {3824 MCRegister VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();3825 if (VCIXDst == VCIXRs1)3826 return Error(VCIXDstLoc, "the destination vector register group cannot"3827 " overlap the source vector register group");3828 }3829 if (MCID.TSFlags & RISCVII::VS2Constraint) {3830 MCRegister VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();3831 if (VCIXDst == VCIXRs2)3832 return Error(VCIXDstLoc, "the destination vector register group cannot"3833 " overlap the source vector register group");3834 }3835 return false;3836 }3837 3838 MCRegister DestReg = Inst.getOperand(0).getReg();3839 unsigned Offset = 0;3840 int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);3841 if (TiedOp == 0)3842 Offset = 1;3843 3844 // Operands[1] will be the first operand, DestReg.3845 SMLoc Loc = Operands[1]->getStartLoc();3846 if (MCID.TSFlags & RISCVII::VS2Constraint) {3847 MCRegister CheckReg = Inst.getOperand(Offset + 1).getReg();3848 if (DestReg == CheckReg)3849 return Error(Loc, "the destination vector register group cannot overlap"3850 " the source vector register group");3851 }3852 if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {3853 MCRegister CheckReg = Inst.getOperand(Offset + 2).getReg();3854 if (DestReg == CheckReg)3855 return Error(Loc, "the destination vector register group cannot overlap"3856 " the source vector register group");3857 }3858 if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {3859 // vadc, vsbc are special cases. These instructions have no mask register.3860 // The destination register could not be V0.3861 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||3862 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||3863 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||3864 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||3865 Opcode == RISCV::VMERGE_VXM)3866 return Error(Loc, "the destination vector register group cannot be V0");3867 3868 // Regardless masked or unmasked version, the number of operands is the3869 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"3870 // actually. We need to check the last operand to ensure whether it is3871 // masked or not.3872 MCRegister CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();3873 assert((CheckReg == RISCV::V0 || !CheckReg) &&3874 "Unexpected register for mask operand");3875 3876 if (DestReg == CheckReg)3877 return Error(Loc, "the destination vector register group cannot overlap"3878 " the mask register");3879 }3880 return false;3881}3882 3883bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,3884 OperandVector &Operands,3885 MCStreamer &Out) {3886 Inst.setLoc(IDLoc);3887 3888 switch (Inst.getOpcode()) {3889 default:3890 break;3891 case RISCV::PseudoC_ADDI_NOP: {3892 if (Inst.getOperand(2).getImm() == 0)3893 emitToStreamer(Out, MCInstBuilder(RISCV::C_NOP));3894 else3895 emitToStreamer(3896 Out, MCInstBuilder(RISCV::C_NOP_HINT).addOperand(Inst.getOperand(2)));3897 return false;3898 }3899 case RISCV::PseudoLLAImm:3900 case RISCV::PseudoLAImm:3901 case RISCV::PseudoLI: {3902 MCRegister Reg = Inst.getOperand(0).getReg();3903 const MCOperand &Op1 = Inst.getOperand(1);3904 if (Op1.isExpr()) {3905 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.3906 // Just convert to an addi. This allows compatibility with gas.3907 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)3908 .addReg(Reg)3909 .addReg(RISCV::X0)3910 .addExpr(Op1.getExpr()));3911 return false;3912 }3913 int64_t Imm = Inst.getOperand(1).getImm();3914 // On RV32 the immediate here can either be a signed or an unsigned3915 // 32-bit number. Sign extension has to be performed to ensure that Imm3916 // represents the expected signed 64-bit number.3917 if (!isRV64())3918 Imm = SignExtend64<32>(Imm);3919 emitLoadImm(Reg, Imm, Out);3920 return false;3921 }3922 case RISCV::PseudoLLA:3923 emitLoadLocalAddress(Inst, IDLoc, Out);3924 return false;3925 case RISCV::PseudoLGA:3926 emitLoadGlobalAddress(Inst, IDLoc, Out);3927 return false;3928 case RISCV::PseudoLA:3929 emitLoadAddress(Inst, IDLoc, Out);3930 return false;3931 case RISCV::PseudoLA_TLS_IE:3932 emitLoadTLSIEAddress(Inst, IDLoc, Out);3933 return false;3934 case RISCV::PseudoLA_TLS_GD:3935 emitLoadTLSGDAddress(Inst, IDLoc, Out);3936 return false;3937 case RISCV::PseudoLB:3938 case RISCV::PseudoQC_E_LB:3939 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);3940 return false;3941 case RISCV::PseudoLBU:3942 case RISCV::PseudoQC_E_LBU:3943 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);3944 return false;3945 case RISCV::PseudoLH:3946 case RISCV::PseudoQC_E_LH:3947 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);3948 return false;3949 case RISCV::PseudoLHU:3950 case RISCV::PseudoQC_E_LHU:3951 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);3952 return false;3953 case RISCV::PseudoLW:3954 case RISCV::PseudoQC_E_LW:3955 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);3956 return false;3957 case RISCV::PseudoLWU:3958 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);3959 return false;3960 case RISCV::PseudoLD:3961 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);3962 return false;3963 case RISCV::PseudoLD_RV32:3964 emitLoadStoreSymbol(Inst, RISCV::LD_RV32, IDLoc, Out, /*HasTmpReg=*/false);3965 return false;3966 case RISCV::PseudoFLH:3967 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);3968 return false;3969 case RISCV::PseudoFLW:3970 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);3971 return false;3972 case RISCV::PseudoFLD:3973 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);3974 return false;3975 case RISCV::PseudoFLQ:3976 emitLoadStoreSymbol(Inst, RISCV::FLQ, IDLoc, Out, /*HasTmpReg=*/true);3977 return false;3978 case RISCV::PseudoSB:3979 case RISCV::PseudoQC_E_SB:3980 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);3981 return false;3982 case RISCV::PseudoSH:3983 case RISCV::PseudoQC_E_SH:3984 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);3985 return false;3986 case RISCV::PseudoSW:3987 case RISCV::PseudoQC_E_SW:3988 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);3989 return false;3990 case RISCV::PseudoSD:3991 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);3992 return false;3993 case RISCV::PseudoSD_RV32:3994 emitLoadStoreSymbol(Inst, RISCV::SD_RV32, IDLoc, Out, /*HasTmpReg=*/true);3995 return false;3996 case RISCV::PseudoFSH:3997 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);3998 return false;3999 case RISCV::PseudoFSW:4000 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);4001 return false;4002 case RISCV::PseudoFSD:4003 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);4004 return false;4005 case RISCV::PseudoFSQ:4006 emitLoadStoreSymbol(Inst, RISCV::FSQ, IDLoc, Out, /*HasTmpReg=*/true);4007 return false;4008 case RISCV::PseudoAddTPRel:4009 if (checkPseudoAddTPRel(Inst, Operands))4010 return true;4011 break;4012 case RISCV::PseudoTLSDESCCall:4013 if (checkPseudoTLSDESCCall(Inst, Operands))4014 return true;4015 break;4016 case RISCV::PseudoSEXT_B:4017 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);4018 return false;4019 case RISCV::PseudoSEXT_H:4020 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);4021 return false;4022 case RISCV::PseudoZEXT_H:4023 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);4024 return false;4025 case RISCV::PseudoZEXT_W:4026 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);4027 return false;4028 case RISCV::PseudoVMSGEU_VX:4029 case RISCV::PseudoVMSGEU_VX_M:4030 case RISCV::PseudoVMSGEU_VX_M_T:4031 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);4032 return false;4033 case RISCV::PseudoVMSGE_VX:4034 case RISCV::PseudoVMSGE_VX_M:4035 case RISCV::PseudoVMSGE_VX_M_T:4036 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);4037 return false;4038 case RISCV::PseudoVMSGE_VI:4039 case RISCV::PseudoVMSLT_VI: {4040 // These instructions are signed and so is immediate so we can subtract one4041 // and change the opcode.4042 int64_t Imm = Inst.getOperand(2).getImm();4043 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI4044 : RISCV::VMSLE_VI;4045 emitToStreamer(Out, MCInstBuilder(Opc)4046 .addOperand(Inst.getOperand(0))4047 .addOperand(Inst.getOperand(1))4048 .addImm(Imm - 1)4049 .addOperand(Inst.getOperand(3))4050 .setLoc(IDLoc));4051 return false;4052 }4053 case RISCV::PseudoVMSGEU_VI:4054 case RISCV::PseudoVMSLTU_VI: {4055 int64_t Imm = Inst.getOperand(2).getImm();4056 // Unsigned comparisons are tricky because the immediate is signed. If the4057 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always4058 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use4059 // vmsne v0, v1, v1 which is always false.4060 if (Imm == 0) {4061 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI4062 ? RISCV::VMSEQ_VV4063 : RISCV::VMSNE_VV;4064 emitToStreamer(Out, MCInstBuilder(Opc)4065 .addOperand(Inst.getOperand(0))4066 .addOperand(Inst.getOperand(1))4067 .addOperand(Inst.getOperand(1))4068 .addOperand(Inst.getOperand(3))4069 .setLoc(IDLoc));4070 } else {4071 // Other immediate values can subtract one like signed.4072 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI4073 ? RISCV::VMSGTU_VI4074 : RISCV::VMSLEU_VI;4075 emitToStreamer(Out, MCInstBuilder(Opc)4076 .addOperand(Inst.getOperand(0))4077 .addOperand(Inst.getOperand(1))4078 .addImm(Imm - 1)4079 .addOperand(Inst.getOperand(3))4080 .setLoc(IDLoc));4081 }4082 4083 return false;4084 }4085 case RISCV::PseudoCV_ELW:4086 emitLoadStoreSymbol(Inst, RISCV::CV_ELW, IDLoc, Out, /*HasTmpReg=*/false);4087 return false;4088 }4089 4090 emitToStreamer(Out, Inst);4091 return false;4092}4093 4094extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void4095LLVMInitializeRISCVAsmParser() {4096 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());4097 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());4098 RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());4099 RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());4100}4101