brintos

brintos / llvm-project-archived public Read only

0
0
Text · 139.4 KiB · 9bb3724 Raw
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