[RISCV] Change func to funct in RISCVInstrInfoXqci.td. NFC (#119669)
[llvm-project.git] / llvm / lib / Target / RISCV / AsmParser / RISCVAsmParser.cpp
blob7c91dc07bbd3e5ebfd6453499101f775b2d5e1f9
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-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/RISCVAsmBackend.h"
10 #include "MCTargetDesc/RISCVBaseInfo.h"
11 #include "MCTargetDesc/RISCVInstPrinter.h"
12 #include "MCTargetDesc/RISCVMCExpr.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/MCAsmLexer.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/MathExtras.h"
40 #include "llvm/Support/RISCVAttributes.h"
41 #include "llvm/TargetParser/RISCVISAInfo.h"
43 #include <limits>
44 #include <optional>
46 using namespace llvm;
48 #define DEBUG_TYPE "riscv-asm-parser"
50 STATISTIC(RISCVNumInstrsCompressed,
51 "Number of RISC-V Compressed instructions emitted");
53 static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",
54 cl::init(false));
56 namespace llvm {
57 extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
58 } // namespace llvm
60 namespace {
61 struct RISCVOperand;
63 struct ParserOptionsSet {
64 bool IsPicEnabled;
67 class RISCVAsmParser : public MCTargetAsmParser {
68 // This tracks the parsing of the 4 operands that make up the vtype portion
69 // of vset(i)vli instructions which are separated by commas. The state names
70 // represent the next expected operand with Done meaning no other operands are
71 // expected.
72 enum VTypeState {
73 VTypeState_SEW,
74 VTypeState_LMUL,
75 VTypeState_TailPolicy,
76 VTypeState_MaskPolicy,
77 VTypeState_Done,
80 SmallVector<FeatureBitset, 4> FeatureBitStack;
82 SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
83 ParserOptionsSet ParserOptions;
85 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
86 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
87 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); }
88 bool enableExperimentalExtension() const {
89 return getSTI().hasFeature(RISCV::Experimental);
92 RISCVTargetStreamer &getTargetStreamer() {
93 assert(getParser().getStreamer().getTargetStreamer() &&
94 "do not have a target streamer");
95 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
96 return static_cast<RISCVTargetStreamer &>(TS);
99 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
100 unsigned Kind) override;
102 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
103 int64_t Lower, int64_t Upper,
104 const Twine &Msg);
105 bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
106 const Twine &Msg);
108 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
109 OperandVector &Operands, MCStreamer &Out,
110 uint64_t &ErrorInfo,
111 bool MatchingInlineAsm) override;
113 MCRegister matchRegisterNameHelper(StringRef Name) const;
114 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
115 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
116 SMLoc &EndLoc) override;
118 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
119 SMLoc NameLoc, OperandVector &Operands) override;
121 ParseStatus parseDirective(AsmToken DirectiveID) override;
123 bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew,
124 unsigned &Lmul, bool &Fractional, bool &TailAgnostic,
125 bool &MaskAgnostic);
126 bool generateVTypeError(SMLoc ErrorLoc);
128 // Helper to actually emit an instruction to the MCStreamer. Also, when
129 // possible, compression of the instruction is performed.
130 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
132 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
133 // synthesize the desired immedate value into the destination register.
134 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
136 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
137 // helpers such as emitLoadLocalAddress and emitLoadAddress.
138 void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
139 const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
140 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
142 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
143 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
145 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
146 void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
148 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
149 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
151 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
152 // addressing.
153 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
155 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
156 // addressing.
157 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
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);
163 // Helper to emit pseudo sign/zero extend instruction.
164 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
165 SMLoc IDLoc, MCStreamer &Out);
167 // Helper to emit pseudo vmsge{u}.vx instruction.
168 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
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 input
172 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
173 // 'add' is an overloaded mnemonic.
174 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
176 // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
177 // Enforcing this using a restricted register class for the output
178 // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
179 // 'jalr' is an overloaded mnemonic.
180 bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);
182 // Check instruction constraints.
183 bool validateInstruction(MCInst &Inst, OperandVector &Operands);
185 /// Helper for processing MC instructions that have been successfully matched
186 /// by matchAndEmitInstruction. Modifications to the emitted instructions,
187 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
188 /// in this method.
189 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
190 MCStreamer &Out);
192 // Auto-generated instruction matching functions
193 #define GET_ASSEMBLER_HEADER
194 #include "RISCVGenAsmMatcher.inc"
196 ParseStatus parseCSRSystemRegister(OperandVector &Operands);
197 ParseStatus parseFPImm(OperandVector &Operands);
198 ParseStatus parseImmediate(OperandVector &Operands);
199 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
200 ParseStatus parseMemOpBaseReg(OperandVector &Operands);
201 ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
202 ParseStatus parseOperandWithModifier(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);
219 ParseStatus parseRegReg(OperandVector &Operands);
220 ParseStatus parseRetval(OperandVector &Operands);
221 ParseStatus parseZcmpStackAdj(OperandVector &Operands,
222 bool ExpectNegative = false);
223 ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {
224 return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);
227 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
229 bool parseDirectiveOption();
230 bool parseDirectiveAttribute();
231 bool parseDirectiveInsn(SMLoc L);
232 bool parseDirectiveVariantCC();
234 /// Helper to reset target features for a new arch string. It
235 /// also records the new arch string that is expanded by RISCVISAInfo
236 /// and reports error for invalid arch string.
237 bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
238 bool FromOptionDirective);
240 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
241 if (!(getSTI().hasFeature(Feature))) {
242 MCSubtargetInfo &STI = copySTI();
243 setAvailableFeatures(
244 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
248 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
249 if (getSTI().hasFeature(Feature)) {
250 MCSubtargetInfo &STI = copySTI();
251 setAvailableFeatures(
252 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
256 void pushFeatureBits() {
257 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
258 "These two stacks must be kept synchronized");
259 FeatureBitStack.push_back(getSTI().getFeatureBits());
260 ParserOptionsStack.push_back(ParserOptions);
263 bool popFeatureBits() {
264 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
265 "These two stacks must be kept synchronized");
266 if (FeatureBitStack.empty())
267 return true;
269 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
270 copySTI().setFeatureBits(FeatureBits);
271 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
273 ParserOptions = ParserOptionsStack.pop_back_val();
275 return false;
278 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
279 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
280 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
282 public:
283 enum RISCVMatchResultTy {
284 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
285 #define GET_OPERAND_DIAGNOSTIC_TYPES
286 #include "RISCVGenAsmMatcher.inc"
287 #undef GET_OPERAND_DIAGNOSTIC_TYPES
290 static bool classifySymbolRef(const MCExpr *Expr,
291 RISCVMCExpr::VariantKind &Kind);
292 static bool isSymbolDiff(const MCExpr *Expr);
294 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
295 const MCInstrInfo &MII, const MCTargetOptions &Options)
296 : MCTargetAsmParser(Options, STI, MII) {
297 MCAsmParserExtension::Initialize(Parser);
299 Parser.addAliasForDirective(".half", ".2byte");
300 Parser.addAliasForDirective(".hword", ".2byte");
301 Parser.addAliasForDirective(".word", ".4byte");
302 Parser.addAliasForDirective(".dword", ".8byte");
303 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
305 auto ABIName = StringRef(Options.ABIName);
306 if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
307 errs() << "Hard-float 'f' ABI can't be used for a target that "
308 "doesn't support the F instruction set extension (ignoring "
309 "target-abi)\n";
310 } else if (ABIName.ends_with("d") &&
311 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
312 errs() << "Hard-float 'd' ABI can't be used for a target that "
313 "doesn't support the D instruction set extension (ignoring "
314 "target-abi)\n";
317 // Use computeTargetABI to check if ABIName is valid. If invalid, output
318 // error message.
319 RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(),
320 ABIName);
322 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
323 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
325 if (AddBuildAttributes)
326 getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
330 /// RISCVOperand - Instances of this class represent a parsed machine
331 /// instruction
332 struct RISCVOperand final : public MCParsedAsmOperand {
334 enum class KindTy {
335 Token,
336 Register,
337 Immediate,
338 FPImmediate,
339 SystemRegister,
340 VType,
341 FRM,
342 Fence,
343 Rlist,
344 Spimm,
345 RegReg,
346 } Kind;
348 struct RegOp {
349 MCRegister RegNum;
350 bool IsGPRAsFPR;
353 struct ImmOp {
354 const MCExpr *Val;
355 bool IsRV64;
358 struct FPImmOp {
359 uint64_t Val;
362 struct SysRegOp {
363 const char *Data;
364 unsigned Length;
365 unsigned Encoding;
366 // FIXME: Add the Encoding parsed fields as needed for checks,
367 // e.g.: read/write or user/supervisor/machine privileges.
370 struct VTypeOp {
371 unsigned Val;
374 struct FRMOp {
375 RISCVFPRndMode::RoundingMode FRM;
378 struct FenceOp {
379 unsigned Val;
382 struct RlistOp {
383 unsigned Val;
386 struct SpimmOp {
387 unsigned Val;
390 struct RegRegOp {
391 MCRegister Reg1;
392 MCRegister Reg2;
395 SMLoc StartLoc, EndLoc;
396 union {
397 StringRef Tok;
398 RegOp Reg;
399 ImmOp Imm;
400 FPImmOp FPImm;
401 struct SysRegOp SysReg;
402 struct VTypeOp VType;
403 struct FRMOp FRM;
404 struct FenceOp Fence;
405 struct RlistOp Rlist;
406 struct SpimmOp Spimm;
407 struct RegRegOp RegReg;
410 RISCVOperand(KindTy K) : Kind(K) {}
412 public:
413 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
414 Kind = o.Kind;
415 StartLoc = o.StartLoc;
416 EndLoc = o.EndLoc;
417 switch (Kind) {
418 case KindTy::Register:
419 Reg = o.Reg;
420 break;
421 case KindTy::Immediate:
422 Imm = o.Imm;
423 break;
424 case KindTy::FPImmediate:
425 FPImm = o.FPImm;
426 break;
427 case KindTy::Token:
428 Tok = o.Tok;
429 break;
430 case KindTy::SystemRegister:
431 SysReg = o.SysReg;
432 break;
433 case KindTy::VType:
434 VType = o.VType;
435 break;
436 case KindTy::FRM:
437 FRM = o.FRM;
438 break;
439 case KindTy::Fence:
440 Fence = o.Fence;
441 break;
442 case KindTy::Rlist:
443 Rlist = o.Rlist;
444 break;
445 case KindTy::Spimm:
446 Spimm = o.Spimm;
447 break;
448 case KindTy::RegReg:
449 RegReg = o.RegReg;
450 break;
454 bool isToken() const override { return Kind == KindTy::Token; }
455 bool isReg() const override { return Kind == KindTy::Register; }
456 bool isV0Reg() const {
457 return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
459 bool isAnyReg() const {
460 return Kind == KindTy::Register &&
461 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) ||
462 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||
463 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));
465 bool isAnyRegC() const {
466 return Kind == KindTy::Register &&
467 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
468 Reg.RegNum) ||
469 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
470 Reg.RegNum));
472 bool isImm() const override { return Kind == KindTy::Immediate; }
473 bool isMem() const override { return false; }
474 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
475 bool isRegReg() const { return Kind == KindTy::RegReg; }
476 bool isRlist() const { return Kind == KindTy::Rlist; }
477 bool isSpimm() const { return Kind == KindTy::Spimm; }
479 bool isGPR() const {
480 return Kind == KindTy::Register &&
481 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
484 bool isGPRPair() const {
485 return Kind == KindTy::Register &&
486 RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
487 Reg.RegNum);
490 bool isGPRF16() const {
491 return Kind == KindTy::Register &&
492 RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(Reg.RegNum);
495 bool isGPRF32() const {
496 return Kind == KindTy::Register &&
497 RISCVMCRegisterClasses[RISCV::GPRF32RegClassID].contains(Reg.RegNum);
500 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
501 bool isGPRAsFPR16() const { return isGPRF16() && Reg.IsGPRAsFPR; }
502 bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
503 bool isGPRPairAsFPR64() const { return isGPRPair() && Reg.IsGPRAsFPR; }
505 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
506 RISCVMCExpr::VariantKind &VK) {
507 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
508 VK = RE->getKind();
509 return RE->evaluateAsConstant(Imm);
512 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
513 VK = RISCVMCExpr::VK_RISCV_None;
514 Imm = CE->getValue();
515 return true;
518 return false;
521 // True if operand is a symbol with no modifiers, or a constant with no
522 // modifiers and isShiftedInt<N-1, 1>(Op).
523 template <int N> bool isBareSimmNLsb0() const {
524 int64_t Imm;
525 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
526 if (!isImm())
527 return false;
528 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
529 bool IsValid;
530 if (!IsConstantImm)
531 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
532 else
533 IsValid = isShiftedInt<N - 1, 1>(Imm);
534 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
537 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
539 bool isBareSymbol() const {
540 int64_t Imm;
541 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
542 // Must be of 'immediate' type but not a constant.
543 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
544 return false;
545 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
546 VK == RISCVMCExpr::VK_RISCV_None;
549 bool isCallSymbol() const {
550 int64_t Imm;
551 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
552 // Must be of 'immediate' type but not a constant.
553 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
554 return false;
555 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
556 (VK == RISCVMCExpr::VK_RISCV_CALL ||
557 VK == RISCVMCExpr::VK_RISCV_CALL_PLT);
560 bool isPseudoJumpSymbol() const {
561 int64_t Imm;
562 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
563 // Must be of 'immediate' type but not a constant.
564 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
565 return false;
566 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
567 VK == RISCVMCExpr::VK_RISCV_CALL;
570 bool isTPRelAddSymbol() const {
571 int64_t Imm;
572 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
573 // Must be of 'immediate' type but not a constant.
574 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
575 return false;
576 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
577 VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
580 bool isTLSDESCCallSymbol() const {
581 int64_t Imm;
582 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
583 // Must be of 'immediate' type but not a constant.
584 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
585 return false;
586 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
587 VK == RISCVMCExpr::VK_RISCV_TLSDESC_CALL;
590 bool isCSRSystemRegister() const { return isSystemRegister(); }
592 bool isVTypeImm(unsigned N) const {
593 int64_t Imm;
594 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
595 if (!isImm())
596 return false;
597 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
598 return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
601 // If the last operand of the vsetvli/vsetvli instruction is a constant
602 // expression, KindTy is Immediate.
603 bool isVTypeI10() const {
604 if (Kind == KindTy::Immediate)
605 return isVTypeImm(10);
606 return Kind == KindTy::VType;
608 bool isVTypeI11() const {
609 if (Kind == KindTy::Immediate)
610 return isVTypeImm(11);
611 return Kind == KindTy::VType;
614 /// Return true if the operand is a valid for the fence instruction e.g.
615 /// ('iorw').
616 bool isFenceArg() const { return Kind == KindTy::Fence; }
618 /// Return true if the operand is a valid floating point rounding mode.
619 bool isFRMArg() const { return Kind == KindTy::FRM; }
620 bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }
621 bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
623 /// Return true if the operand is a valid fli.s floating-point immediate.
624 bool isLoadFPImm() const {
625 if (isImm())
626 return isUImm5();
627 if (Kind != KindTy::FPImmediate)
628 return false;
629 int Idx = RISCVLoadFPImm::getLoadFPImm(
630 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
631 // Don't allow decimal version of the minimum value. It is a different value
632 // for each supported data type.
633 return Idx >= 0 && Idx != 1;
636 bool isImmXLenLI() const {
637 int64_t Imm;
638 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
639 if (!isImm())
640 return false;
641 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
642 if (VK == RISCVMCExpr::VK_RISCV_LO ||
643 VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
644 VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
645 VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO)
646 return true;
647 // Given only Imm, ensuring that the actually specified constant is either
648 // a signed or unsigned 64-bit number is unfortunately impossible.
649 if (IsConstantImm) {
650 return VK == RISCVMCExpr::VK_RISCV_None &&
651 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
654 return RISCVAsmParser::isSymbolDiff(getImm());
657 bool isImmXLenLI_Restricted() const {
658 int64_t Imm;
659 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
660 if (!isImm())
661 return false;
662 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
663 // 'la imm' supports constant immediates only.
664 return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
665 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
668 bool isUImmLog2XLen() const {
669 int64_t Imm;
670 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
671 if (!isImm())
672 return false;
673 if (!evaluateConstantImm(getImm(), Imm, VK) ||
674 VK != RISCVMCExpr::VK_RISCV_None)
675 return false;
676 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
679 bool isUImmLog2XLenNonZero() const {
680 int64_t Imm;
681 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
682 if (!isImm())
683 return false;
684 if (!evaluateConstantImm(getImm(), Imm, VK) ||
685 VK != RISCVMCExpr::VK_RISCV_None)
686 return false;
687 if (Imm == 0)
688 return false;
689 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
692 bool isUImmLog2XLenHalf() const {
693 int64_t Imm;
694 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
695 if (!isImm())
696 return false;
697 if (!evaluateConstantImm(getImm(), Imm, VK) ||
698 VK != RISCVMCExpr::VK_RISCV_None)
699 return false;
700 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
703 template <unsigned N> bool IsUImm() const {
704 int64_t Imm;
705 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
706 if (!isImm())
707 return false;
708 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
709 return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
712 bool isUImm1() const { return IsUImm<1>(); }
713 bool isUImm2() const { return IsUImm<2>(); }
714 bool isUImm3() const { return IsUImm<3>(); }
715 bool isUImm4() const { return IsUImm<4>(); }
716 bool isUImm5() const { return IsUImm<5>(); }
717 bool isUImm6() const { return IsUImm<6>(); }
718 bool isUImm7() const { return IsUImm<7>(); }
719 bool isUImm8() const { return IsUImm<8>(); }
720 bool isUImm11() const { return IsUImm<11>(); }
721 bool isUImm16() const { return IsUImm<16>(); }
722 bool isUImm20() const { return IsUImm<20>(); }
723 bool isUImm32() const { return IsUImm<32>(); }
724 bool isUImm48() const { return IsUImm<48>(); }
725 bool isUImm64() const { return IsUImm<64>(); }
727 bool isUImm8GE32() const {
728 int64_t Imm;
729 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
730 if (!isImm())
731 return false;
732 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
733 return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&
734 VK == RISCVMCExpr::VK_RISCV_None;
737 bool isRnumArg() const {
738 int64_t Imm;
739 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
740 if (!isImm())
741 return false;
742 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
743 return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
744 VK == RISCVMCExpr::VK_RISCV_None;
747 bool isRnumArg_0_7() const {
748 int64_t Imm;
749 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
750 if (!isImm())
751 return false;
752 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
753 return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) &&
754 VK == RISCVMCExpr::VK_RISCV_None;
757 bool isRnumArg_1_10() const {
758 int64_t Imm;
759 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
760 if (!isImm())
761 return false;
762 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
763 return IsConstantImm && Imm >= INT64_C(1) && Imm <= INT64_C(10) &&
764 VK == RISCVMCExpr::VK_RISCV_None;
767 bool isRnumArg_2_14() const {
768 int64_t Imm;
769 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
770 if (!isImm())
771 return false;
772 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
773 return IsConstantImm && Imm >= INT64_C(2) && Imm <= INT64_C(14) &&
774 VK == RISCVMCExpr::VK_RISCV_None;
777 bool isSImm5() const {
778 if (!isImm())
779 return false;
780 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
781 int64_t Imm;
782 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
783 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
784 VK == RISCVMCExpr::VK_RISCV_None;
787 bool isSImm6() const {
788 if (!isImm())
789 return false;
790 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
791 int64_t Imm;
792 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
793 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
794 VK == RISCVMCExpr::VK_RISCV_None;
797 bool isSImm6NonZero() const {
798 if (!isImm())
799 return false;
800 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
801 int64_t Imm;
802 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
803 return IsConstantImm && Imm != 0 &&
804 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
805 VK == RISCVMCExpr::VK_RISCV_None;
808 bool isCLUIImm() const {
809 if (!isImm())
810 return false;
811 int64_t Imm;
812 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
813 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
814 return IsConstantImm && (Imm != 0) &&
815 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
816 VK == RISCVMCExpr::VK_RISCV_None;
819 bool isUImm2Lsb0() const {
820 if (!isImm())
821 return false;
822 int64_t Imm;
823 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
824 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
825 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
826 VK == RISCVMCExpr::VK_RISCV_None;
829 bool isUImm5Lsb0() const {
830 if (!isImm())
831 return false;
832 int64_t Imm;
833 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
834 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
835 return IsConstantImm && isShiftedUInt<4, 1>(Imm) &&
836 VK == RISCVMCExpr::VK_RISCV_None;
839 bool isUImm6Lsb0() const {
840 if (!isImm())
841 return false;
842 int64_t Imm;
843 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
844 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
845 return IsConstantImm && isShiftedUInt<5, 1>(Imm) &&
846 VK == RISCVMCExpr::VK_RISCV_None;
849 bool isUImm7Lsb00() const {
850 if (!isImm())
851 return false;
852 int64_t Imm;
853 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
854 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
855 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
856 VK == RISCVMCExpr::VK_RISCV_None;
859 bool isUImm8Lsb00() const {
860 if (!isImm())
861 return false;
862 int64_t Imm;
863 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
864 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
865 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
866 VK == RISCVMCExpr::VK_RISCV_None;
869 bool isUImm8Lsb000() const {
870 if (!isImm())
871 return false;
872 int64_t Imm;
873 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
874 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
875 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
876 VK == RISCVMCExpr::VK_RISCV_None;
879 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
881 bool isUImm9Lsb000() const {
882 if (!isImm())
883 return false;
884 int64_t Imm;
885 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
886 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
887 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
888 VK == RISCVMCExpr::VK_RISCV_None;
891 bool isUImm10Lsb00NonZero() const {
892 if (!isImm())
893 return false;
894 int64_t Imm;
895 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
896 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
897 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
898 VK == RISCVMCExpr::VK_RISCV_None;
901 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
902 // This allows writing 'addi a0, a0, 0xffffffff'.
903 static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
904 if (IsRV64Imm || !isUInt<32>(Imm))
905 return Imm;
906 return SignExtend64<32>(Imm);
909 bool isSImm12() const {
910 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
911 int64_t Imm;
912 bool IsValid;
913 if (!isImm())
914 return false;
915 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
916 if (!IsConstantImm)
917 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
918 else
919 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
920 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
921 VK == RISCVMCExpr::VK_RISCV_LO ||
922 VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
923 VK == RISCVMCExpr::VK_RISCV_TPREL_LO ||
924 VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
925 VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO);
928 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
930 bool isSImm12Lsb00000() const {
931 if (!isImm())
932 return false;
933 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
934 int64_t Imm;
935 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
936 return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
937 VK == RISCVMCExpr::VK_RISCV_None;
940 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
942 bool isSImm10Lsb0000NonZero() const {
943 if (!isImm())
944 return false;
945 int64_t Imm;
946 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
947 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
948 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
949 VK == RISCVMCExpr::VK_RISCV_None;
952 bool isUImm20LUI() const {
953 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
954 int64_t Imm;
955 bool IsValid;
956 if (!isImm())
957 return false;
958 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
959 if (!IsConstantImm) {
960 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
961 return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
962 VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
963 } else {
964 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
965 VK == RISCVMCExpr::VK_RISCV_HI ||
966 VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
970 bool isUImm20AUIPC() const {
971 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
972 int64_t Imm;
973 bool IsValid;
974 if (!isImm())
975 return false;
976 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
977 if (!IsConstantImm) {
978 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
979 return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
980 VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
981 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
982 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
983 VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
986 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
987 VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
988 VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
989 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
990 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
991 VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
994 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
996 bool isImmZero() const {
997 if (!isImm())
998 return false;
999 int64_t Imm;
1000 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1001 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1002 return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
1005 bool isSImm5Plus1() const {
1006 if (!isImm())
1007 return false;
1008 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1009 int64_t Imm;
1010 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1011 return IsConstantImm &&
1012 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
1013 VK == RISCVMCExpr::VK_RISCV_None;
1016 /// getStartLoc - Gets location of the first token of this operand
1017 SMLoc getStartLoc() const override { return StartLoc; }
1018 /// getEndLoc - Gets location of the last token of this operand
1019 SMLoc getEndLoc() const override { return EndLoc; }
1020 /// True if this operand is for an RV64 instruction
1021 bool isRV64Imm() const {
1022 assert(Kind == KindTy::Immediate && "Invalid type access!");
1023 return Imm.IsRV64;
1026 MCRegister getReg() const override {
1027 assert(Kind == KindTy::Register && "Invalid type access!");
1028 return Reg.RegNum;
1031 StringRef getSysReg() const {
1032 assert(Kind == KindTy::SystemRegister && "Invalid type access!");
1033 return StringRef(SysReg.Data, SysReg.Length);
1036 const MCExpr *getImm() const {
1037 assert(Kind == KindTy::Immediate && "Invalid type access!");
1038 return Imm.Val;
1041 uint64_t getFPConst() const {
1042 assert(Kind == KindTy::FPImmediate && "Invalid type access!");
1043 return FPImm.Val;
1046 StringRef getToken() const {
1047 assert(Kind == KindTy::Token && "Invalid type access!");
1048 return Tok;
1051 unsigned getVType() const {
1052 assert(Kind == KindTy::VType && "Invalid type access!");
1053 return VType.Val;
1056 RISCVFPRndMode::RoundingMode getFRM() const {
1057 assert(Kind == KindTy::FRM && "Invalid type access!");
1058 return FRM.FRM;
1061 unsigned getFence() const {
1062 assert(Kind == KindTy::Fence && "Invalid type access!");
1063 return Fence.Val;
1066 void print(raw_ostream &OS) const override {
1067 auto RegName = [](MCRegister Reg) {
1068 if (Reg)
1069 return RISCVInstPrinter::getRegisterName(Reg);
1070 else
1071 return "noreg";
1074 switch (Kind) {
1075 case KindTy::Immediate:
1076 OS << *getImm();
1077 break;
1078 case KindTy::FPImmediate:
1079 break;
1080 case KindTy::Register:
1081 OS << "<register " << RegName(getReg()) << ">";
1082 break;
1083 case KindTy::Token:
1084 OS << "'" << getToken() << "'";
1085 break;
1086 case KindTy::SystemRegister:
1087 OS << "<sysreg: " << getSysReg() << '>';
1088 break;
1089 case KindTy::VType:
1090 OS << "<vtype: ";
1091 RISCVVType::printVType(getVType(), OS);
1092 OS << '>';
1093 break;
1094 case KindTy::FRM:
1095 OS << "<frm: ";
1096 roundingModeToString(getFRM());
1097 OS << '>';
1098 break;
1099 case KindTy::Fence:
1100 OS << "<fence: ";
1101 OS << getFence();
1102 OS << '>';
1103 break;
1104 case KindTy::Rlist:
1105 OS << "<rlist: ";
1106 RISCVZC::printRlist(Rlist.Val, OS);
1107 OS << '>';
1108 break;
1109 case KindTy::Spimm:
1110 OS << "<Spimm: ";
1111 OS << Spimm.Val;
1112 OS << '>';
1113 break;
1114 case KindTy::RegReg:
1115 OS << "<RegReg: Reg1 " << RegName(RegReg.Reg1);
1116 OS << " Reg2 " << RegName(RegReg.Reg2);
1117 break;
1121 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
1122 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1123 Op->Tok = Str;
1124 Op->StartLoc = S;
1125 Op->EndLoc = S;
1126 return Op;
1129 static std::unique_ptr<RISCVOperand>
1130 createReg(MCRegister Reg, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
1131 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1132 Op->Reg.RegNum = Reg.id();
1133 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1134 Op->StartLoc = S;
1135 Op->EndLoc = E;
1136 return Op;
1139 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
1140 SMLoc E, bool IsRV64) {
1141 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1142 Op->Imm.Val = Val;
1143 Op->Imm.IsRV64 = IsRV64;
1144 Op->StartLoc = S;
1145 Op->EndLoc = E;
1146 return Op;
1149 static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
1150 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1151 Op->FPImm.Val = Val;
1152 Op->StartLoc = S;
1153 Op->EndLoc = S;
1154 return Op;
1157 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
1158 unsigned Encoding) {
1159 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1160 Op->SysReg.Data = Str.data();
1161 Op->SysReg.Length = Str.size();
1162 Op->SysReg.Encoding = Encoding;
1163 Op->StartLoc = S;
1164 Op->EndLoc = S;
1165 return Op;
1168 static std::unique_ptr<RISCVOperand>
1169 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
1170 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1171 Op->FRM.FRM = FRM;
1172 Op->StartLoc = S;
1173 Op->EndLoc = S;
1174 return Op;
1177 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
1178 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1179 Op->Fence.Val = Val;
1180 Op->StartLoc = S;
1181 Op->EndLoc = S;
1182 return Op;
1185 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
1186 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1187 Op->VType.Val = VTypeI;
1188 Op->StartLoc = S;
1189 Op->EndLoc = S;
1190 return Op;
1193 static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,
1194 SMLoc S) {
1195 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1196 Op->Rlist.Val = RlistEncode;
1197 Op->StartLoc = S;
1198 return Op;
1201 static std::unique_ptr<RISCVOperand> createRegReg(MCRegister Reg1,
1202 MCRegister Reg2, SMLoc S) {
1203 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1204 Op->RegReg.Reg1 = Reg1.id();
1205 Op->RegReg.Reg2 = Reg2.id();
1206 Op->StartLoc = S;
1207 Op->EndLoc = S;
1208 return Op;
1211 static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {
1212 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1213 Op->Spimm.Val = Spimm;
1214 Op->StartLoc = S;
1215 return Op;
1218 static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
1219 assert(Expr && "Expr shouldn't be null!");
1220 int64_t Imm = 0;
1221 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1222 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1224 if (IsConstant)
1225 Inst.addOperand(
1226 MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
1227 else
1228 Inst.addOperand(MCOperand::createExpr(Expr));
1231 // Used by the TableGen Code
1232 void addRegOperands(MCInst &Inst, unsigned N) const {
1233 assert(N == 1 && "Invalid number of operands!");
1234 Inst.addOperand(MCOperand::createReg(getReg()));
1237 void addImmOperands(MCInst &Inst, unsigned N) const {
1238 assert(N == 1 && "Invalid number of operands!");
1239 addExpr(Inst, getImm(), isRV64Imm());
1242 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
1244 if (isImm()) {
1245 addExpr(Inst, getImm(), isRV64Imm());
1246 return;
1249 int Imm = RISCVLoadFPImm::getLoadFPImm(
1250 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1251 Inst.addOperand(MCOperand::createImm(Imm));
1254 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
1256 Inst.addOperand(MCOperand::createImm(Fence.Val));
1259 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
1261 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
1264 // Support non-canonical syntax:
1265 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1266 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1267 void addVTypeIOperands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
1269 int64_t Imm = 0;
1270 if (Kind == KindTy::Immediate) {
1271 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1272 [[maybe_unused]] bool IsConstantImm =
1273 evaluateConstantImm(getImm(), Imm, VK);
1274 assert(IsConstantImm && "Invalid VTypeI Operand!");
1275 } else {
1276 Imm = getVType();
1278 Inst.addOperand(MCOperand::createImm(Imm));
1281 void addRlistOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 Inst.addOperand(MCOperand::createImm(Rlist.Val));
1286 void addRegRegOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 2 && "Invalid number of operands!");
1288 Inst.addOperand(MCOperand::createReg(RegReg.Reg1));
1289 Inst.addOperand(MCOperand::createReg(RegReg.Reg2));
1292 void addSpimmOperands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
1294 Inst.addOperand(MCOperand::createImm(Spimm.Val));
1297 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
1299 Inst.addOperand(MCOperand::createImm(getFRM()));
1302 } // end anonymous namespace.
1304 #define GET_REGISTER_MATCHER
1305 #define GET_SUBTARGET_FEATURE_NAME
1306 #define GET_MATCHER_IMPLEMENTATION
1307 #define GET_MNEMONIC_SPELL_CHECKER
1308 #include "RISCVGenAsmMatcher.inc"
1310 static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
1311 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1312 return Reg - RISCV::F0_D + RISCV::F0_H;
1315 static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
1316 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1317 return Reg - RISCV::F0_D + RISCV::F0_F;
1320 static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
1321 unsigned Kind) {
1322 unsigned RegClassID;
1323 if (Kind == MCK_VRM2)
1324 RegClassID = RISCV::VRM2RegClassID;
1325 else if (Kind == MCK_VRM4)
1326 RegClassID = RISCV::VRM4RegClassID;
1327 else if (Kind == MCK_VRM8)
1328 RegClassID = RISCV::VRM8RegClassID;
1329 else
1330 return MCRegister();
1331 return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
1332 &RISCVMCRegisterClasses[RegClassID]);
1335 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1336 unsigned Kind) {
1337 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1338 if (!Op.isReg())
1339 return Match_InvalidOperand;
1341 MCRegister Reg = Op.getReg();
1342 bool IsRegFPR64 =
1343 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1344 bool IsRegFPR64C =
1345 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1346 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1348 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1349 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1350 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1351 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1352 Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
1353 return Match_Success;
1355 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1356 // register from FPR64 to FPR16 if necessary.
1357 if (IsRegFPR64 && Kind == MCK_FPR16) {
1358 Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1359 return Match_Success;
1361 if (Kind == MCK_GPRAsFPR16 && Op.isGPRAsFPR()) {
1362 Op.Reg.RegNum = Reg - RISCV::X0 + RISCV::X0_H;
1363 return Match_Success;
1365 if (Kind == MCK_GPRAsFPR32 && Op.isGPRAsFPR()) {
1366 Op.Reg.RegNum = Reg - RISCV::X0 + RISCV::X0_W;
1367 return Match_Success;
1370 // There are some GPRF64AsFPR instructions that have no RV32 equivalent. We
1371 // reject them at parsing thinking we should match as GPRPairAsFPR for RV32.
1372 // So we explicitly accept them here for RV32 to allow the generic code to
1373 // report that the instruction requires RV64.
1374 if (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg) &&
1375 Kind == MCK_GPRF64AsFPR && STI->hasFeature(RISCV::FeatureStdExtZdinx) &&
1376 !isRV64())
1377 return Match_Success;
1379 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1380 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1381 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1382 Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1383 if (!Op.Reg.RegNum)
1384 return Match_InvalidOperand;
1385 return Match_Success;
1387 return Match_InvalidOperand;
1390 bool RISCVAsmParser::generateImmOutOfRangeError(
1391 SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
1392 const Twine &Msg = "immediate must be an integer in the range") {
1393 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1396 bool RISCVAsmParser::generateImmOutOfRangeError(
1397 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1398 const Twine &Msg = "immediate must be an integer in the range") {
1399 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1400 return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);
1403 bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1404 OperandVector &Operands,
1405 MCStreamer &Out,
1406 uint64_t &ErrorInfo,
1407 bool MatchingInlineAsm) {
1408 MCInst Inst;
1409 FeatureBitset MissingFeatures;
1411 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1412 MatchingInlineAsm);
1413 switch (Result) {
1414 default:
1415 break;
1416 case Match_Success:
1417 if (validateInstruction(Inst, Operands))
1418 return true;
1419 return processInstruction(Inst, IDLoc, Operands, Out);
1420 case Match_MissingFeature: {
1421 assert(MissingFeatures.any() && "Unknown missing features!");
1422 bool FirstFeature = true;
1423 std::string Msg = "instruction requires the following:";
1424 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1425 if (MissingFeatures[i]) {
1426 Msg += FirstFeature ? " " : ", ";
1427 Msg += getSubtargetFeatureName(i);
1428 FirstFeature = false;
1431 return Error(IDLoc, Msg);
1433 case Match_MnemonicFail: {
1434 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1435 std::string Suggestion = RISCVMnemonicSpellCheck(
1436 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1437 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1439 case Match_InvalidOperand: {
1440 SMLoc ErrorLoc = IDLoc;
1441 if (ErrorInfo != ~0ULL) {
1442 if (ErrorInfo >= Operands.size())
1443 return Error(ErrorLoc, "too few operands for instruction");
1445 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1446 if (ErrorLoc == SMLoc())
1447 ErrorLoc = IDLoc;
1449 return Error(ErrorLoc, "invalid operand for instruction");
1453 // Handle the case when the error message is of specific type
1454 // other than the generic Match_InvalidOperand, and the
1455 // corresponding operand is missing.
1456 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1457 SMLoc ErrorLoc = IDLoc;
1458 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1459 return Error(ErrorLoc, "too few operands for instruction");
1462 switch (Result) {
1463 default:
1464 break;
1465 case Match_InvalidImmXLenLI:
1466 if (isRV64()) {
1467 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1468 return Error(ErrorLoc, "operand must be a constant 64-bit integer");
1470 return generateImmOutOfRangeError(Operands, ErrorInfo,
1471 std::numeric_limits<int32_t>::min(),
1472 std::numeric_limits<uint32_t>::max());
1473 case Match_InvalidImmXLenLI_Restricted:
1474 if (isRV64()) {
1475 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1476 return Error(ErrorLoc, "operand either must be a constant 64-bit integer "
1477 "or a bare symbol name");
1479 return generateImmOutOfRangeError(
1480 Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),
1481 std::numeric_limits<uint32_t>::max(),
1482 "operand either must be a bare symbol name or an immediate integer in "
1483 "the range");
1484 case Match_InvalidImmZero: {
1485 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1486 return Error(ErrorLoc, "immediate must be zero");
1488 case Match_InvalidUImmLog2XLen:
1489 if (isRV64())
1490 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1491 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1492 case Match_InvalidUImmLog2XLenNonZero:
1493 if (isRV64())
1494 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
1495 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
1496 case Match_InvalidUImm1:
1497 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
1498 case Match_InvalidUImm2:
1499 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1500 case Match_InvalidUImm2Lsb0:
1501 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
1502 "immediate must be one of");
1503 case Match_InvalidUImm3:
1504 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
1505 case Match_InvalidUImm4:
1506 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1507 case Match_InvalidUImm5:
1508 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1509 case Match_InvalidUImm6:
1510 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1511 case Match_InvalidUImm7:
1512 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
1513 case Match_InvalidUImm8:
1514 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
1515 case Match_InvalidUImm8GE32:
1516 return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);
1517 case Match_InvalidSImm5:
1518 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1519 (1 << 4) - 1);
1520 case Match_InvalidSImm6:
1521 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1522 (1 << 5) - 1);
1523 case Match_InvalidSImm6NonZero:
1524 return generateImmOutOfRangeError(
1525 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1526 "immediate must be non-zero in the range");
1527 case Match_InvalidCLUIImm:
1528 return generateImmOutOfRangeError(
1529 Operands, ErrorInfo, 1, (1 << 5) - 1,
1530 "immediate must be in [0xfffe0, 0xfffff] or");
1531 case Match_InvalidUImm5Lsb0:
1532 return generateImmOutOfRangeError(
1533 Operands, ErrorInfo, 0, (1 << 5) - 2,
1534 "immediate must be a multiple of 2 bytes in the range");
1535 case Match_InvalidUImm6Lsb0:
1536 return generateImmOutOfRangeError(
1537 Operands, ErrorInfo, 0, (1 << 6) - 2,
1538 "immediate must be a multiple of 2 bytes in the range");
1539 case Match_InvalidUImm7Lsb00:
1540 return generateImmOutOfRangeError(
1541 Operands, ErrorInfo, 0, (1 << 7) - 4,
1542 "immediate must be a multiple of 4 bytes in the range");
1543 case Match_InvalidUImm8Lsb00:
1544 return generateImmOutOfRangeError(
1545 Operands, ErrorInfo, 0, (1 << 8) - 4,
1546 "immediate must be a multiple of 4 bytes in the range");
1547 case Match_InvalidUImm8Lsb000:
1548 return generateImmOutOfRangeError(
1549 Operands, ErrorInfo, 0, (1 << 8) - 8,
1550 "immediate must be a multiple of 8 bytes in the range");
1551 case Match_InvalidSImm9Lsb0:
1552 return generateImmOutOfRangeError(
1553 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1554 "immediate must be a multiple of 2 bytes in the range");
1555 case Match_InvalidUImm9Lsb000:
1556 return generateImmOutOfRangeError(
1557 Operands, ErrorInfo, 0, (1 << 9) - 8,
1558 "immediate must be a multiple of 8 bytes in the range");
1559 case Match_InvalidUImm10Lsb00NonZero:
1560 return generateImmOutOfRangeError(
1561 Operands, ErrorInfo, 4, (1 << 10) - 4,
1562 "immediate must be a multiple of 4 bytes in the range");
1563 case Match_InvalidSImm10Lsb0000NonZero:
1564 return generateImmOutOfRangeError(
1565 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1566 "immediate must be a multiple of 16 bytes and non-zero in the range");
1567 case Match_InvalidUImm11:
1568 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 11) - 1);
1569 case Match_InvalidSImm12:
1570 return generateImmOutOfRangeError(
1571 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1572 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1573 "integer in the range");
1574 case Match_InvalidSImm12Lsb0:
1575 return generateImmOutOfRangeError(
1576 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1577 "immediate must be a multiple of 2 bytes in the range");
1578 case Match_InvalidSImm12Lsb00000:
1579 return generateImmOutOfRangeError(
1580 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
1581 "immediate must be a multiple of 32 bytes in the range");
1582 case Match_InvalidSImm13Lsb0:
1583 return generateImmOutOfRangeError(
1584 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1585 "immediate must be a multiple of 2 bytes in the range");
1586 case Match_InvalidUImm20LUI:
1587 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1588 "operand must be a symbol with "
1589 "%hi/%tprel_hi modifier or an integer in "
1590 "the range");
1591 case Match_InvalidUImm20:
1592 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
1593 case Match_InvalidUImm20AUIPC:
1594 return generateImmOutOfRangeError(
1595 Operands, ErrorInfo, 0, (1 << 20) - 1,
1596 "operand must be a symbol with a "
1597 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1598 "an integer in the range");
1599 case Match_InvalidSImm21Lsb0JAL:
1600 return generateImmOutOfRangeError(
1601 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1602 "immediate must be a multiple of 2 bytes in the range");
1603 case Match_InvalidCSRSystemRegister: {
1604 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1605 "operand must be a valid system register "
1606 "name or an integer in the range");
1608 case Match_InvalidLoadFPImm: {
1609 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1610 return Error(ErrorLoc, "operand must be a valid floating-point constant");
1612 case Match_InvalidBareSymbol: {
1613 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1614 return Error(ErrorLoc, "operand must be a bare symbol name");
1616 case Match_InvalidPseudoJumpSymbol: {
1617 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1618 return Error(ErrorLoc, "operand must be a valid jump target");
1620 case Match_InvalidCallSymbol: {
1621 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1622 return Error(ErrorLoc, "operand must be a bare symbol name");
1624 case Match_InvalidTPRelAddSymbol: {
1625 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1626 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1628 case Match_InvalidTLSDESCCallSymbol: {
1629 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1630 return Error(ErrorLoc,
1631 "operand must be a symbol with %tlsdesc_call modifier");
1633 case Match_InvalidRTZArg: {
1634 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1635 return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
1637 case Match_InvalidVTypeI: {
1638 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1639 return generateVTypeError(ErrorLoc);
1641 case Match_InvalidVMaskRegister: {
1642 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1643 return Error(ErrorLoc, "operand must be v0.t");
1645 case Match_InvalidSImm5Plus1: {
1646 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1647 (1 << 4),
1648 "immediate must be in the range");
1650 case Match_InvalidRlist: {
1651 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1652 return Error(
1653 ErrorLoc,
1654 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1656 case Match_InvalidStackAdj: {
1657 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1658 return Error(
1659 ErrorLoc,
1660 "stack adjustment is invalid for this instruction and register list; "
1661 "refer to Zc spec for a detailed range of stack adjustment");
1663 case Match_InvalidRnumArg: {
1664 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1666 case Match_InvalidRegReg: {
1667 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1668 return Error(ErrorLoc, "operands must be register and register");
1672 llvm_unreachable("Unknown match type detected!");
1675 // Attempts to match Name as a register (either using the default name or
1676 // alternative ABI names), returning the matching register. Upon failure,
1677 // returns a non-valid MCRegister. If IsRVE, then registers x16-x31 will be
1678 // rejected.
1679 MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
1680 MCRegister Reg = MatchRegisterName(Name);
1681 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1682 // match always matches the 64-bit variant, and not the 16/32-bit one.
1683 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1684 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1685 // The default FPR register class is based on the tablegen enum ordering.
1686 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1687 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1688 if (!Reg)
1689 Reg = MatchRegisterAltName(Name);
1690 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1691 Reg = MCRegister();
1692 return Reg;
1695 bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1696 SMLoc &EndLoc) {
1697 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1698 return Error(StartLoc, "invalid register name");
1699 return false;
1702 ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1703 SMLoc &EndLoc) {
1704 const AsmToken &Tok = getParser().getTok();
1705 StartLoc = Tok.getLoc();
1706 EndLoc = Tok.getEndLoc();
1707 StringRef Name = getLexer().getTok().getIdentifier();
1709 Reg = matchRegisterNameHelper(Name);
1710 if (!Reg)
1711 return ParseStatus::NoMatch;
1713 getParser().Lex(); // Eat identifier token.
1714 return ParseStatus::Success;
1717 ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1718 bool AllowParens) {
1719 SMLoc FirstS = getLoc();
1720 bool HadParens = false;
1721 AsmToken LParen;
1723 // If this is an LParen and a parenthesised register name is allowed, parse it
1724 // atomically.
1725 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1726 AsmToken Buf[2];
1727 size_t ReadCount = getLexer().peekTokens(Buf);
1728 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1729 HadParens = true;
1730 LParen = getParser().getTok();
1731 getParser().Lex(); // Eat '('
1735 switch (getLexer().getKind()) {
1736 default:
1737 if (HadParens)
1738 getLexer().UnLex(LParen);
1739 return ParseStatus::NoMatch;
1740 case AsmToken::Identifier:
1741 StringRef Name = getLexer().getTok().getIdentifier();
1742 MCRegister Reg = matchRegisterNameHelper(Name);
1744 if (!Reg) {
1745 if (HadParens)
1746 getLexer().UnLex(LParen);
1747 return ParseStatus::NoMatch;
1749 if (HadParens)
1750 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1751 SMLoc S = getLoc();
1752 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
1753 getLexer().Lex();
1754 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
1757 if (HadParens) {
1758 getParser().Lex(); // Eat ')'
1759 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1762 return ParseStatus::Success;
1765 ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1766 SMLoc S = getLoc();
1767 SMLoc E;
1768 const MCExpr *Res;
1770 switch (getLexer().getKind()) {
1771 default:
1772 return ParseStatus::NoMatch;
1773 case AsmToken::LParen:
1774 case AsmToken::Minus:
1775 case AsmToken::Plus:
1776 case AsmToken::Exclaim:
1777 case AsmToken::Tilde:
1778 case AsmToken::Integer:
1779 case AsmToken::String: {
1780 if (getParser().parseExpression(Res, E))
1781 return ParseStatus::Failure;
1783 auto *CE = dyn_cast<MCConstantExpr>(Res);
1784 if (CE) {
1785 int64_t Imm = CE->getValue();
1786 if (isUInt<7>(Imm)) {
1787 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1788 return ParseStatus::Success;
1792 break;
1794 case AsmToken::Identifier: {
1795 StringRef Identifier;
1796 if (getParser().parseIdentifier(Identifier))
1797 return ParseStatus::Failure;
1799 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1800 if (Opcode) {
1801 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1802 "Unexpected opcode");
1803 Res = MCConstantExpr::create(Opcode->Value, getContext());
1804 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1805 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1806 return ParseStatus::Success;
1809 break;
1811 case AsmToken::Percent:
1812 break;
1815 return generateImmOutOfRangeError(
1816 S, 0, 127,
1817 "opcode must be a valid opcode name or an immediate in the range");
1820 ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
1821 SMLoc S = getLoc();
1822 SMLoc E;
1823 const MCExpr *Res;
1825 switch (getLexer().getKind()) {
1826 default:
1827 return ParseStatus::NoMatch;
1828 case AsmToken::LParen:
1829 case AsmToken::Minus:
1830 case AsmToken::Plus:
1831 case AsmToken::Exclaim:
1832 case AsmToken::Tilde:
1833 case AsmToken::Integer:
1834 case AsmToken::String: {
1835 if (getParser().parseExpression(Res, E))
1836 return ParseStatus::Failure;
1838 auto *CE = dyn_cast<MCConstantExpr>(Res);
1839 if (CE) {
1840 int64_t Imm = CE->getValue();
1841 if (Imm >= 0 && Imm <= 2) {
1842 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1843 return ParseStatus::Success;
1847 break;
1849 case AsmToken::Identifier: {
1850 StringRef Identifier;
1851 if (getParser().parseIdentifier(Identifier))
1852 return ParseStatus::Failure;
1854 unsigned Opcode;
1855 if (Identifier == "C0")
1856 Opcode = 0;
1857 else if (Identifier == "C1")
1858 Opcode = 1;
1859 else if (Identifier == "C2")
1860 Opcode = 2;
1861 else
1862 break;
1864 Res = MCConstantExpr::create(Opcode, getContext());
1865 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1866 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1867 return ParseStatus::Success;
1869 case AsmToken::Percent: {
1870 // Discard operand with modifier.
1871 break;
1875 return generateImmOutOfRangeError(
1876 S, 0, 2,
1877 "opcode must be a valid opcode name or an immediate in the range");
1880 ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1881 SMLoc S = getLoc();
1882 const MCExpr *Res;
1884 auto SysRegFromConstantInt = [this](const MCExpr *E, SMLoc S) {
1885 if (auto *CE = dyn_cast<MCConstantExpr>(E)) {
1886 int64_t Imm = CE->getValue();
1887 if (isUInt<12>(Imm)) {
1888 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1889 // Accept an immediate representing a named Sys Reg if it satisfies the
1890 // the required features.
1891 for (auto &Reg : Range) {
1892 if (Reg.haveRequiredFeatures(STI->getFeatureBits()))
1893 return RISCVOperand::createSysReg(Reg.Name, S, Imm);
1895 // Accept an immediate representing an un-named Sys Reg if the range is
1896 // valid, regardless of the required features.
1897 return RISCVOperand::createSysReg("", S, Imm);
1900 return std::unique_ptr<RISCVOperand>();
1903 switch (getLexer().getKind()) {
1904 default:
1905 return ParseStatus::NoMatch;
1906 case AsmToken::LParen:
1907 case AsmToken::Minus:
1908 case AsmToken::Plus:
1909 case AsmToken::Exclaim:
1910 case AsmToken::Tilde:
1911 case AsmToken::Integer:
1912 case AsmToken::String: {
1913 if (getParser().parseExpression(Res))
1914 return ParseStatus::Failure;
1916 if (auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1917 Operands.push_back(std::move(SysOpnd));
1918 return ParseStatus::Success;
1921 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1923 case AsmToken::Identifier: {
1924 StringRef Identifier;
1925 if (getParser().parseIdentifier(Identifier))
1926 return ParseStatus::Failure;
1928 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1929 if (!SysReg)
1930 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1931 if (!SysReg)
1932 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1933 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1934 SysReg->Name + "'");
1936 // Accept a named Sys Reg if the required features are present.
1937 if (SysReg) {
1938 const auto &FeatureBits = getSTI().getFeatureBits();
1939 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
1940 const auto *Feature = llvm::find_if(RISCVFeatureKV, [&](auto Feature) {
1941 return SysReg->FeaturesRequired[Feature.Value];
1943 auto ErrorMsg = std::string("system register '") + SysReg->Name + "' ";
1944 if (SysReg->isRV32Only && FeatureBits[RISCV::Feature64Bit]) {
1945 ErrorMsg += "is RV32 only";
1946 if (Feature != std::end(RISCVFeatureKV))
1947 ErrorMsg += " and ";
1949 if (Feature != std::end(RISCVFeatureKV)) {
1950 ErrorMsg +=
1951 "requires '" + std::string(Feature->Key) + "' to be enabled";
1954 return Error(S, ErrorMsg);
1956 Operands.push_back(
1957 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1958 return ParseStatus::Success;
1961 // Accept a symbol name that evaluates to an absolute value.
1962 MCSymbol *Sym = getContext().lookupSymbol(Identifier);
1963 if (Sym && Sym->isVariable()) {
1964 // Pass false for SetUsed, since redefining the value later does not
1965 // affect this instruction.
1966 if (auto SysOpnd = SysRegFromConstantInt(
1967 Sym->getVariableValue(/*SetUsed=*/false), S)) {
1968 Operands.push_back(std::move(SysOpnd));
1969 return ParseStatus::Success;
1973 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
1974 "operand must be a valid system register "
1975 "name or an integer in the range");
1977 case AsmToken::Percent: {
1978 // Discard operand with modifier.
1979 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1983 return ParseStatus::NoMatch;
1986 ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
1987 SMLoc S = getLoc();
1989 // Parse special floats (inf/nan/min) representation.
1990 if (getTok().is(AsmToken::Identifier)) {
1991 StringRef Identifier = getTok().getIdentifier();
1992 if (Identifier.compare_insensitive("inf") == 0) {
1993 Operands.push_back(
1994 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
1995 getTok().getEndLoc(), isRV64()));
1996 } else if (Identifier.compare_insensitive("nan") == 0) {
1997 Operands.push_back(
1998 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
1999 getTok().getEndLoc(), isRV64()));
2000 } else if (Identifier.compare_insensitive("min") == 0) {
2001 Operands.push_back(
2002 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
2003 getTok().getEndLoc(), isRV64()));
2004 } else {
2005 return TokError("invalid floating point literal");
2008 Lex(); // Eat the token.
2010 return ParseStatus::Success;
2013 // Handle negation, as that still comes through as a separate token.
2014 bool IsNegative = parseOptionalToken(AsmToken::Minus);
2016 const AsmToken &Tok = getTok();
2017 if (!Tok.is(AsmToken::Real))
2018 return TokError("invalid floating point immediate");
2020 // Parse FP representation.
2021 APFloat RealVal(APFloat::IEEEdouble());
2022 auto StatusOrErr =
2023 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2024 if (errorToBool(StatusOrErr.takeError()))
2025 return TokError("invalid floating point representation");
2027 if (IsNegative)
2028 RealVal.changeSign();
2030 Operands.push_back(RISCVOperand::createFPImm(
2031 RealVal.bitcastToAPInt().getZExtValue(), S));
2033 Lex(); // Eat the token.
2035 return ParseStatus::Success;
2038 ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {
2039 SMLoc S = getLoc();
2040 SMLoc E;
2041 const MCExpr *Res;
2043 switch (getLexer().getKind()) {
2044 default:
2045 return ParseStatus::NoMatch;
2046 case AsmToken::LParen:
2047 case AsmToken::Dot:
2048 case AsmToken::Minus:
2049 case AsmToken::Plus:
2050 case AsmToken::Exclaim:
2051 case AsmToken::Tilde:
2052 case AsmToken::Integer:
2053 case AsmToken::String:
2054 case AsmToken::Identifier:
2055 if (getParser().parseExpression(Res, E))
2056 return ParseStatus::Failure;
2057 break;
2058 case AsmToken::Percent:
2059 return parseOperandWithModifier(Operands);
2062 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2063 return ParseStatus::Success;
2066 ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
2067 SMLoc S = getLoc();
2068 SMLoc E;
2070 if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
2071 return ParseStatus::Failure;
2073 if (getLexer().getKind() != AsmToken::Identifier)
2074 return Error(getLoc(), "expected valid identifier for operand modifier");
2075 StringRef Identifier = getParser().getTok().getIdentifier();
2076 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
2077 if (VK == RISCVMCExpr::VK_RISCV_Invalid)
2078 return Error(getLoc(), "unrecognized operand modifier");
2080 getParser().Lex(); // Eat the identifier
2081 if (parseToken(AsmToken::LParen, "expected '('"))
2082 return ParseStatus::Failure;
2084 const MCExpr *SubExpr;
2085 if (getParser().parseParenExpression(SubExpr, E))
2086 return ParseStatus::Failure;
2088 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
2089 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
2090 return ParseStatus::Success;
2093 ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
2094 SMLoc S = getLoc();
2095 const MCExpr *Res;
2097 if (getLexer().getKind() != AsmToken::Identifier)
2098 return ParseStatus::NoMatch;
2100 StringRef Identifier;
2101 AsmToken Tok = getLexer().getTok();
2103 if (getParser().parseIdentifier(Identifier))
2104 return ParseStatus::Failure;
2106 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
2108 if (Identifier.consume_back("@plt"))
2109 return Error(getLoc(), "'@plt' operand not valid for instruction");
2111 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2113 if (Sym->isVariable()) {
2114 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
2115 if (!isa<MCSymbolRefExpr>(V)) {
2116 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
2117 return ParseStatus::NoMatch;
2119 Res = V;
2120 } else
2121 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
2123 MCBinaryExpr::Opcode Opcode;
2124 switch (getLexer().getKind()) {
2125 default:
2126 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2127 return ParseStatus::Success;
2128 case AsmToken::Plus:
2129 Opcode = MCBinaryExpr::Add;
2130 getLexer().Lex();
2131 break;
2132 case AsmToken::Minus:
2133 Opcode = MCBinaryExpr::Sub;
2134 getLexer().Lex();
2135 break;
2138 const MCExpr *Expr;
2139 if (getParser().parseExpression(Expr, E))
2140 return ParseStatus::Failure;
2141 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
2142 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2143 return ParseStatus::Success;
2146 ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2147 SMLoc S = getLoc();
2148 const MCExpr *Res;
2150 if (getLexer().getKind() != AsmToken::Identifier)
2151 return ParseStatus::NoMatch;
2153 // Avoid parsing the register in `call rd, foo` as a call symbol.
2154 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
2155 return ParseStatus::NoMatch;
2157 StringRef Identifier;
2158 if (getParser().parseIdentifier(Identifier))
2159 return ParseStatus::Failure;
2161 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
2163 RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
2164 (void)Identifier.consume_back("@plt");
2166 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2167 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
2168 Res = RISCVMCExpr::create(Res, Kind, getContext());
2169 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2170 return ParseStatus::Success;
2173 ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2174 SMLoc S = getLoc();
2175 SMLoc E;
2176 const MCExpr *Res;
2178 if (getParser().parseExpression(Res, E))
2179 return ParseStatus::Failure;
2181 if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
2182 cast<MCSymbolRefExpr>(Res)->getKind() ==
2183 MCSymbolRefExpr::VariantKind::VK_PLT)
2184 return Error(S, "operand must be a valid jump target");
2186 Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
2187 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2188 return ParseStatus::Success;
2191 ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2192 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2193 // both being acceptable forms. When parsing `jal ra, foo` this function
2194 // will be called for the `ra` register operand in an attempt to match the
2195 // single-operand alias. parseJALOffset must fail for this case. It would
2196 // seem logical to try parse the operand using parseImmediate and return
2197 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2198 // the second form rather than the first). We can't do this as there's no
2199 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2200 // is an identifier and is followed by a comma.
2201 if (getLexer().is(AsmToken::Identifier) &&
2202 getLexer().peekTok().is(AsmToken::Comma))
2203 return ParseStatus::NoMatch;
2205 return parseImmediate(Operands);
2208 bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
2209 unsigned &Sew, unsigned &Lmul,
2210 bool &Fractional, bool &TailAgnostic,
2211 bool &MaskAgnostic) {
2212 if (Tok.isNot(AsmToken::Identifier))
2213 return true;
2215 StringRef Identifier = Tok.getIdentifier();
2217 switch (State) {
2218 case VTypeState_SEW:
2219 if (!Identifier.consume_front("e"))
2220 break;
2221 if (Identifier.getAsInteger(10, Sew))
2222 break;
2223 if (!RISCVVType::isValidSEW(Sew))
2224 break;
2225 State = VTypeState_LMUL;
2226 return false;
2227 case VTypeState_LMUL: {
2228 if (!Identifier.consume_front("m"))
2229 break;
2230 Fractional = Identifier.consume_front("f");
2231 if (Identifier.getAsInteger(10, Lmul))
2232 break;
2233 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2234 break;
2236 if (Fractional) {
2237 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2238 unsigned MinLMUL = ELEN / 8;
2239 if (Lmul > MinLMUL)
2240 Warning(Tok.getLoc(),
2241 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2242 Twine(MinLMUL) + " is reserved");
2245 State = VTypeState_TailPolicy;
2246 return false;
2248 case VTypeState_TailPolicy:
2249 if (Identifier == "ta")
2250 TailAgnostic = true;
2251 else if (Identifier == "tu")
2252 TailAgnostic = false;
2253 else
2254 break;
2255 State = VTypeState_MaskPolicy;
2256 return false;
2257 case VTypeState_MaskPolicy:
2258 if (Identifier == "ma")
2259 MaskAgnostic = true;
2260 else if (Identifier == "mu")
2261 MaskAgnostic = false;
2262 else
2263 break;
2264 State = VTypeState_Done;
2265 return false;
2266 case VTypeState_Done:
2267 // Extra token?
2268 break;
2271 return true;
2274 ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2275 SMLoc S = getLoc();
2277 unsigned Sew = 0;
2278 unsigned Lmul = 0;
2279 bool Fractional = false;
2280 bool TailAgnostic = false;
2281 bool MaskAgnostic = false;
2283 VTypeState State = VTypeState_SEW;
2284 SMLoc SEWLoc = S;
2286 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2287 MaskAgnostic))
2288 return ParseStatus::NoMatch;
2290 getLexer().Lex();
2292 while (parseOptionalToken(AsmToken::Comma)) {
2293 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2294 MaskAgnostic))
2295 break;
2297 getLexer().Lex();
2300 if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {
2301 RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2302 if (Fractional) {
2303 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2304 unsigned MaxSEW = ELEN / Lmul;
2305 // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2306 if (MaxSEW >= 8 && Sew > MaxSEW)
2307 Warning(SEWLoc,
2308 "use of vtype encodings with SEW > " + Twine(MaxSEW) +
2309 " and LMUL == mf" + Twine(Lmul) +
2310 " may not be compatible with all RVV implementations");
2313 unsigned VTypeI =
2314 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
2315 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2316 return ParseStatus::Success;
2319 return generateVTypeError(S);
2322 bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2323 return Error(
2324 ErrorLoc,
2325 "operand must be "
2326 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2329 ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2330 if (getLexer().isNot(AsmToken::Identifier))
2331 return ParseStatus::NoMatch;
2333 StringRef Name = getLexer().getTok().getIdentifier();
2334 if (!Name.consume_back(".t"))
2335 return Error(getLoc(), "expected '.t' suffix");
2336 MCRegister Reg = matchRegisterNameHelper(Name);
2338 if (!Reg)
2339 return ParseStatus::NoMatch;
2340 if (Reg != RISCV::V0)
2341 return ParseStatus::NoMatch;
2342 SMLoc S = getLoc();
2343 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2344 getLexer().Lex();
2345 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2346 return ParseStatus::Success;
2349 ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
2350 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2351 return ParseStatus::NoMatch;
2353 return parseGPRAsFPR(Operands);
2356 ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2357 if (getLexer().isNot(AsmToken::Identifier))
2358 return ParseStatus::NoMatch;
2360 StringRef Name = getLexer().getTok().getIdentifier();
2361 MCRegister Reg = matchRegisterNameHelper(Name);
2363 if (!Reg)
2364 return ParseStatus::NoMatch;
2365 SMLoc S = getLoc();
2366 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2367 getLexer().Lex();
2368 Operands.push_back(RISCVOperand::createReg(
2369 Reg, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2370 return ParseStatus::Success;
2373 ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
2374 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2375 return ParseStatus::NoMatch;
2377 if (getLexer().isNot(AsmToken::Identifier))
2378 return ParseStatus::NoMatch;
2380 StringRef Name = getLexer().getTok().getIdentifier();
2381 MCRegister Reg = matchRegisterNameHelper(Name);
2383 if (!Reg)
2384 return ParseStatus::NoMatch;
2386 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2387 return ParseStatus::NoMatch;
2389 if ((Reg - RISCV::X0) & 1) {
2390 // Only report the even register error if we have at least Zfinx so we know
2391 // some FP is enabled. We already checked F earlier.
2392 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2393 return TokError("double precision floating point operands must use even "
2394 "numbered X register");
2395 return ParseStatus::NoMatch;
2398 SMLoc S = getLoc();
2399 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2400 getLexer().Lex();
2402 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2403 MCRegister Pair = RI->getMatchingSuperReg(
2404 Reg, RISCV::sub_gpr_even,
2405 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2406 Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));
2407 return ParseStatus::Success;
2410 template <bool IsRV64>
2411 ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2412 return parseGPRPair(Operands, IsRV64);
2415 ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2416 bool IsRV64Inst) {
2417 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2418 // RV64 as it will prevent matching the RV64 version of the same instruction
2419 // that doesn't use a GPRPair.
2420 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2421 // still parse as a pair.
2422 if (!IsRV64Inst && isRV64())
2423 return ParseStatus::NoMatch;
2425 if (getLexer().isNot(AsmToken::Identifier))
2426 return ParseStatus::NoMatch;
2428 StringRef Name = getLexer().getTok().getIdentifier();
2429 MCRegister Reg = matchRegisterNameHelper(Name);
2431 if (!Reg)
2432 return ParseStatus::NoMatch;
2434 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2435 return ParseStatus::NoMatch;
2437 if ((Reg - RISCV::X0) & 1)
2438 return TokError("register must be even");
2440 SMLoc S = getLoc();
2441 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2442 getLexer().Lex();
2444 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2445 MCRegister Pair = RI->getMatchingSuperReg(
2446 Reg, RISCV::sub_gpr_even,
2447 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2448 Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2449 return ParseStatus::Success;
2452 ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2453 if (getLexer().isNot(AsmToken::Identifier))
2454 return TokError(
2455 "operand must be a valid floating point rounding mode mnemonic");
2457 StringRef Str = getLexer().getTok().getIdentifier();
2458 RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);
2460 if (FRM == RISCVFPRndMode::Invalid)
2461 return TokError(
2462 "operand must be a valid floating point rounding mode mnemonic");
2464 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2465 Lex(); // Eat identifier token.
2466 return ParseStatus::Success;
2469 ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2470 const AsmToken &Tok = getLexer().getTok();
2472 if (Tok.is(AsmToken::Integer)) {
2473 if (Tok.getIntVal() != 0)
2474 goto ParseFail;
2476 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2477 Lex();
2478 return ParseStatus::Success;
2481 if (Tok.is(AsmToken::Identifier)) {
2482 StringRef Str = Tok.getIdentifier();
2484 // Letters must be unique, taken from 'iorw', and in ascending order. This
2485 // holds as long as each individual character is one of 'iorw' and is
2486 // greater than the previous character.
2487 unsigned Imm = 0;
2488 bool Valid = true;
2489 char Prev = '\0';
2490 for (char c : Str) {
2491 switch (c) {
2492 default:
2493 Valid = false;
2494 break;
2495 case 'i':
2496 Imm |= RISCVFenceField::I;
2497 break;
2498 case 'o':
2499 Imm |= RISCVFenceField::O;
2500 break;
2501 case 'r':
2502 Imm |= RISCVFenceField::R;
2503 break;
2504 case 'w':
2505 Imm |= RISCVFenceField::W;
2506 break;
2509 if (c <= Prev) {
2510 Valid = false;
2511 break;
2513 Prev = c;
2516 if (!Valid)
2517 goto ParseFail;
2519 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2520 Lex();
2521 return ParseStatus::Success;
2524 ParseFail:
2525 return TokError("operand must be formed of letters selected in-order from "
2526 "'iorw' or be 0");
2529 ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2530 if (parseToken(AsmToken::LParen, "expected '('"))
2531 return ParseStatus::Failure;
2532 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2534 if (!parseRegister(Operands).isSuccess())
2535 return Error(getLoc(), "expected register");
2537 if (parseToken(AsmToken::RParen, "expected ')'"))
2538 return ParseStatus::Failure;
2539 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2541 return ParseStatus::Success;
2544 ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2545 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2546 // as one of their register operands, such as `(a0)`. This just denotes that
2547 // the register (in this case `a0`) contains a memory address.
2549 // Normally, we would be able to parse these by putting the parens into the
2550 // instruction string. However, GNU as also accepts a zero-offset memory
2551 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2552 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2553 // do not accept an immediate operand, and we do not want to add a "dummy"
2554 // operand that is silently dropped.
2556 // Instead, we use this custom parser. This will: allow (and discard) an
2557 // offset if it is zero; require (and discard) parentheses; and add only the
2558 // parsed register operand to `Operands`.
2560 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2561 // which will only print the register surrounded by parentheses (which GNU as
2562 // also uses as its canonical representation for these operands).
2563 std::unique_ptr<RISCVOperand> OptionalImmOp;
2565 if (getLexer().isNot(AsmToken::LParen)) {
2566 // Parse an Integer token. We do not accept arbritrary constant expressions
2567 // in the offset field (because they may include parens, which complicates
2568 // parsing a lot).
2569 int64_t ImmVal;
2570 SMLoc ImmStart = getLoc();
2571 if (getParser().parseIntToken(ImmVal,
2572 "expected '(' or optional integer offset"))
2573 return ParseStatus::Failure;
2575 // Create a RISCVOperand for checking later (so the error messages are
2576 // nicer), but we don't add it to Operands.
2577 SMLoc ImmEnd = getLoc();
2578 OptionalImmOp =
2579 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
2580 ImmStart, ImmEnd, isRV64());
2583 if (parseToken(AsmToken::LParen,
2584 OptionalImmOp ? "expected '(' after optional integer offset"
2585 : "expected '(' or optional integer offset"))
2586 return ParseStatus::Failure;
2588 if (!parseRegister(Operands).isSuccess())
2589 return Error(getLoc(), "expected register");
2591 if (parseToken(AsmToken::RParen, "expected ')'"))
2592 return ParseStatus::Failure;
2594 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2595 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2596 return Error(
2597 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2598 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2600 return ParseStatus::Success;
2603 ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2604 // RR : a2(a1)
2605 if (getLexer().getKind() != AsmToken::Identifier)
2606 return ParseStatus::NoMatch;
2608 StringRef RegName = getLexer().getTok().getIdentifier();
2609 MCRegister Reg = matchRegisterNameHelper(RegName);
2610 if (!Reg)
2611 return Error(getLoc(), "invalid register");
2612 getLexer().Lex();
2614 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
2615 return ParseStatus::Failure;
2617 if (getLexer().getKind() != AsmToken::Identifier)
2618 return Error(getLoc(), "expected register");
2620 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2621 MCRegister Reg2 = matchRegisterNameHelper(Reg2Name);
2622 if (!Reg2)
2623 return Error(getLoc(), "invalid register");
2624 getLexer().Lex();
2626 if (parseToken(AsmToken::RParen, "expected ')'"))
2627 return ParseStatus::Failure;
2629 Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));
2631 return ParseStatus::Success;
2634 ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
2635 // Rlist: {ra [, s0[-sN]]}
2636 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2637 SMLoc S = getLoc();
2639 if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
2640 return ParseStatus::Failure;
2642 bool IsEABI = isRVE();
2644 if (getLexer().isNot(AsmToken::Identifier))
2645 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2647 StringRef RegName = getLexer().getTok().getIdentifier();
2648 MCRegister RegStart = matchRegisterNameHelper(RegName);
2649 MCRegister RegEnd;
2650 if (RegStart != RISCV::X1)
2651 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2652 getLexer().Lex();
2654 // parse case like ,s0
2655 if (parseOptionalToken(AsmToken::Comma)) {
2656 if (getLexer().isNot(AsmToken::Identifier))
2657 return Error(getLoc(), "invalid register");
2658 StringRef RegName = getLexer().getTok().getIdentifier();
2659 RegStart = matchRegisterNameHelper(RegName);
2660 if (!RegStart)
2661 return Error(getLoc(), "invalid register");
2662 if (RegStart != RISCV::X8)
2663 return Error(getLoc(),
2664 "continuous register list must start from 's0' or 'x8'");
2665 getLexer().Lex(); // eat reg
2668 // parse case like -s1
2669 if (parseOptionalToken(AsmToken::Minus)) {
2670 StringRef EndName = getLexer().getTok().getIdentifier();
2671 // FIXME: the register mapping and checks of EABI is wrong
2672 RegEnd = matchRegisterNameHelper(EndName);
2673 if (!RegEnd)
2674 return Error(getLoc(), "invalid register");
2675 if (IsEABI && RegEnd != RISCV::X9)
2676 return Error(getLoc(), "contiguous register list of EABI can only be "
2677 "'s0-s1' or 'x8-x9' pair");
2678 getLexer().Lex();
2681 if (!IsEABI) {
2682 // parse extra part like ', x18[-x20]' for XRegList
2683 if (parseOptionalToken(AsmToken::Comma)) {
2684 if (RegEnd != RISCV::X9)
2685 return Error(
2686 getLoc(),
2687 "first contiguous registers pair of register list must be 'x8-x9'");
2689 // parse ', x18' for extra part
2690 if (getLexer().isNot(AsmToken::Identifier))
2691 return Error(getLoc(), "invalid register");
2692 StringRef EndName = getLexer().getTok().getIdentifier();
2693 if (MatchRegisterName(EndName) != RISCV::X18)
2694 return Error(getLoc(),
2695 "second contiguous registers pair of register list "
2696 "must start from 'x18'");
2697 getLexer().Lex();
2699 // parse '-x20' for extra part
2700 if (parseOptionalToken(AsmToken::Minus)) {
2701 if (getLexer().isNot(AsmToken::Identifier))
2702 return Error(getLoc(), "invalid register");
2703 EndName = getLexer().getTok().getIdentifier();
2704 if (!MatchRegisterName(EndName))
2705 return Error(getLoc(), "invalid register");
2706 getLexer().Lex();
2708 RegEnd = MatchRegisterName(EndName);
2712 if (RegEnd == RISCV::X26)
2713 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2714 "x18-x26} is not supported");
2716 if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
2717 return ParseStatus::Failure;
2719 if (!RegEnd)
2720 RegEnd = RegStart;
2722 auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
2723 if (Encode == RISCVZC::INVALID_RLIST)
2724 return Error(S, "invalid register list");
2725 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2727 return ParseStatus::Success;
2730 ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2731 bool ExpectNegative) {
2732 bool Negative = parseOptionalToken(AsmToken::Minus);
2734 SMLoc S = getLoc();
2735 int64_t StackAdjustment = getLexer().getTok().getIntVal();
2736 unsigned Spimm = 0;
2737 unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
2739 if (Negative != ExpectNegative ||
2740 !RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64()))
2741 return ParseStatus::NoMatch;
2742 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2743 getLexer().Lex();
2744 return ParseStatus::Success;
2747 /// Looks at a token type and creates the relevant operand from this
2748 /// information, adding to Operands. If operand was parsed, returns false, else
2749 /// true.
2750 bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2751 // Check if the current operand has a custom associated parser, if so, try to
2752 // custom parse the operand, or fallback to the general approach.
2753 ParseStatus Result =
2754 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
2755 if (Result.isSuccess())
2756 return false;
2757 if (Result.isFailure())
2758 return true;
2760 // Attempt to parse token as a register.
2761 if (parseRegister(Operands, true).isSuccess())
2762 return false;
2764 // Attempt to parse token as an immediate
2765 if (parseImmediate(Operands).isSuccess()) {
2766 // Parse memory base register if present
2767 if (getLexer().is(AsmToken::LParen))
2768 return !parseMemOpBaseReg(Operands).isSuccess();
2769 return false;
2772 // Finally we have exhausted all options and must declare defeat.
2773 Error(getLoc(), "unknown operand");
2774 return true;
2777 bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,
2778 StringRef Name, SMLoc NameLoc,
2779 OperandVector &Operands) {
2780 // Ensure that if the instruction occurs when relaxation is enabled,
2781 // relocations are forced for the file. Ideally this would be done when there
2782 // is enough information to reliably determine if the instruction itself may
2783 // cause relaxations. Unfortunately instruction processing stage occurs in the
2784 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2785 // for the entire file.
2786 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2787 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2788 if (Assembler != nullptr) {
2789 RISCVAsmBackend &MAB =
2790 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
2791 MAB.setForceRelocs();
2795 // First operand is token for instruction
2796 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
2798 // If there are no more operands, then finish
2799 if (getLexer().is(AsmToken::EndOfStatement)) {
2800 getParser().Lex(); // Consume the EndOfStatement.
2801 return false;
2804 // Parse first operand
2805 if (parseOperand(Operands, Name))
2806 return true;
2808 // Parse until end of statement, consuming commas between operands
2809 while (parseOptionalToken(AsmToken::Comma)) {
2810 // Parse next operand
2811 if (parseOperand(Operands, Name))
2812 return true;
2815 if (getParser().parseEOL("unexpected token")) {
2816 getParser().eatToEndOfStatement();
2817 return true;
2819 return false;
2822 bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2823 RISCVMCExpr::VariantKind &Kind) {
2824 Kind = RISCVMCExpr::VK_RISCV_None;
2826 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2827 Kind = RE->getKind();
2828 Expr = RE->getSubExpr();
2831 MCValue Res;
2832 MCFixup Fixup;
2833 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2834 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
2835 return false;
2838 bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
2839 MCValue Res;
2840 MCFixup Fixup;
2841 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
2842 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
2843 Res.getSymB();
2845 return false;
2848 ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
2849 StringRef IDVal = DirectiveID.getString();
2851 if (IDVal == ".option")
2852 return parseDirectiveOption();
2853 if (IDVal == ".attribute")
2854 return parseDirectiveAttribute();
2855 if (IDVal == ".insn")
2856 return parseDirectiveInsn(DirectiveID.getLoc());
2857 if (IDVal == ".variant_cc")
2858 return parseDirectiveVariantCC();
2860 return ParseStatus::NoMatch;
2863 bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
2864 bool FromOptionDirective) {
2865 for (auto &Feature : RISCVFeatureKV)
2866 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
2867 clearFeatureBits(Feature.Value, Feature.Key);
2869 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2870 Arch, /*EnableExperimentalExtension=*/true,
2871 /*ExperimentalExtensionVersionCheck=*/true);
2872 if (!ParseResult) {
2873 std::string Buffer;
2874 raw_string_ostream OutputErrMsg(Buffer);
2875 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2876 OutputErrMsg << "invalid arch name '" << Arch << "', "
2877 << ErrMsg.getMessage();
2880 return Error(Loc, OutputErrMsg.str());
2882 auto &ISAInfo = *ParseResult;
2884 for (auto &Feature : RISCVFeatureKV)
2885 if (ISAInfo->hasExtension(Feature.Key))
2886 setFeatureBits(Feature.Value, Feature.Key);
2888 if (FromOptionDirective) {
2889 if (ISAInfo->getXLen() == 32 && isRV64())
2890 return Error(Loc, "bad arch string switching from rv64 to rv32");
2891 else if (ISAInfo->getXLen() == 64 && !isRV64())
2892 return Error(Loc, "bad arch string switching from rv32 to rv64");
2895 if (ISAInfo->getXLen() == 32)
2896 clearFeatureBits(RISCV::Feature64Bit, "64bit");
2897 else if (ISAInfo->getXLen() == 64)
2898 setFeatureBits(RISCV::Feature64Bit, "64bit");
2899 else
2900 return Error(Loc, "bad arch string " + Arch);
2902 Result = ISAInfo->toString();
2903 return false;
2906 bool RISCVAsmParser::parseDirectiveOption() {
2907 MCAsmParser &Parser = getParser();
2908 // Get the option token.
2909 AsmToken Tok = Parser.getTok();
2911 // At the moment only identifiers are supported.
2912 if (parseToken(AsmToken::Identifier, "expected identifier"))
2913 return true;
2915 StringRef Option = Tok.getIdentifier();
2917 if (Option == "push") {
2918 if (Parser.parseEOL())
2919 return true;
2921 getTargetStreamer().emitDirectiveOptionPush();
2922 pushFeatureBits();
2923 return false;
2926 if (Option == "pop") {
2927 SMLoc StartLoc = Parser.getTok().getLoc();
2928 if (Parser.parseEOL())
2929 return true;
2931 getTargetStreamer().emitDirectiveOptionPop();
2932 if (popFeatureBits())
2933 return Error(StartLoc, ".option pop with no .option push");
2935 return false;
2938 if (Option == "arch") {
2939 SmallVector<RISCVOptionArchArg> Args;
2940 do {
2941 if (Parser.parseComma())
2942 return true;
2944 RISCVOptionArchArgType Type;
2945 if (parseOptionalToken(AsmToken::Plus))
2946 Type = RISCVOptionArchArgType::Plus;
2947 else if (parseOptionalToken(AsmToken::Minus))
2948 Type = RISCVOptionArchArgType::Minus;
2949 else if (!Args.empty())
2950 return Error(Parser.getTok().getLoc(),
2951 "unexpected token, expected + or -");
2952 else
2953 Type = RISCVOptionArchArgType::Full;
2955 if (Parser.getTok().isNot(AsmToken::Identifier))
2956 return Error(Parser.getTok().getLoc(),
2957 "unexpected token, expected identifier");
2959 StringRef Arch = Parser.getTok().getString();
2960 SMLoc Loc = Parser.getTok().getLoc();
2961 Parser.Lex();
2963 if (Type == RISCVOptionArchArgType::Full) {
2964 std::string Result;
2965 if (resetToArch(Arch, Loc, Result, true))
2966 return true;
2968 Args.emplace_back(Type, Result);
2969 break;
2972 if (isDigit(Arch.back()))
2973 return Error(
2974 Loc, "extension version number parsing not currently implemented");
2976 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
2977 if (!enableExperimentalExtension() &&
2978 StringRef(Feature).starts_with("experimental-"))
2979 return Error(Loc, "unexpected experimental extensions");
2980 auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);
2981 if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)
2982 return Error(Loc, "unknown extension feature");
2984 Args.emplace_back(Type, Arch.str());
2986 if (Type == RISCVOptionArchArgType::Plus) {
2987 FeatureBitset OldFeatureBits = STI->getFeatureBits();
2989 setFeatureBits(Ext->Value, Ext->Key);
2990 auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());
2991 if (!ParseResult) {
2992 copySTI().setFeatureBits(OldFeatureBits);
2993 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
2995 std::string Buffer;
2996 raw_string_ostream OutputErrMsg(Buffer);
2997 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2998 OutputErrMsg << ErrMsg.getMessage();
3001 return Error(Loc, OutputErrMsg.str());
3003 } else {
3004 assert(Type == RISCVOptionArchArgType::Minus);
3005 // It is invalid to disable an extension that there are other enabled
3006 // extensions depend on it.
3007 // TODO: Make use of RISCVISAInfo to handle this
3008 for (auto &Feature : RISCVFeatureKV) {
3009 if (getSTI().hasFeature(Feature.Value) &&
3010 Feature.Implies.test(Ext->Value))
3011 return Error(Loc, Twine("can't disable ") + Ext->Key +
3012 " extension; " + Feature.Key +
3013 " extension requires " + Ext->Key +
3014 " extension");
3017 clearFeatureBits(Ext->Value, Ext->Key);
3019 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
3021 if (Parser.parseEOL())
3022 return true;
3024 getTargetStreamer().emitDirectiveOptionArch(Args);
3025 return false;
3028 if (Option == "rvc") {
3029 if (Parser.parseEOL())
3030 return true;
3032 getTargetStreamer().emitDirectiveOptionRVC();
3033 setFeatureBits(RISCV::FeatureStdExtC, "c");
3034 return false;
3037 if (Option == "norvc") {
3038 if (Parser.parseEOL())
3039 return true;
3041 getTargetStreamer().emitDirectiveOptionNoRVC();
3042 clearFeatureBits(RISCV::FeatureStdExtC, "c");
3043 clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
3044 return false;
3047 if (Option == "pic") {
3048 if (Parser.parseEOL())
3049 return true;
3051 getTargetStreamer().emitDirectiveOptionPIC();
3052 ParserOptions.IsPicEnabled = true;
3053 return false;
3056 if (Option == "nopic") {
3057 if (Parser.parseEOL())
3058 return true;
3060 getTargetStreamer().emitDirectiveOptionNoPIC();
3061 ParserOptions.IsPicEnabled = false;
3062 return false;
3065 if (Option == "relax") {
3066 if (Parser.parseEOL())
3067 return true;
3069 getTargetStreamer().emitDirectiveOptionRelax();
3070 setFeatureBits(RISCV::FeatureRelax, "relax");
3071 return false;
3074 if (Option == "norelax") {
3075 if (Parser.parseEOL())
3076 return true;
3078 getTargetStreamer().emitDirectiveOptionNoRelax();
3079 clearFeatureBits(RISCV::FeatureRelax, "relax");
3080 return false;
3083 // Unknown option.
3084 Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
3085 "'rvc', 'norvc', 'arch', 'relax' or "
3086 "'norelax'");
3087 Parser.eatToEndOfStatement();
3088 return false;
3091 /// parseDirectiveAttribute
3092 /// ::= .attribute expression ',' ( expression | "string" )
3093 /// ::= .attribute identifier ',' ( expression | "string" )
3094 bool RISCVAsmParser::parseDirectiveAttribute() {
3095 MCAsmParser &Parser = getParser();
3096 int64_t Tag;
3097 SMLoc TagLoc;
3098 TagLoc = Parser.getTok().getLoc();
3099 if (Parser.getTok().is(AsmToken::Identifier)) {
3100 StringRef Name = Parser.getTok().getIdentifier();
3101 std::optional<unsigned> Ret =
3102 ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());
3103 if (!Ret)
3104 return Error(TagLoc, "attribute name not recognised: " + Name);
3105 Tag = *Ret;
3106 Parser.Lex();
3107 } else {
3108 const MCExpr *AttrExpr;
3110 TagLoc = Parser.getTok().getLoc();
3111 if (Parser.parseExpression(AttrExpr))
3112 return true;
3114 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
3115 if (check(!CE, TagLoc, "expected numeric constant"))
3116 return true;
3118 Tag = CE->getValue();
3121 if (Parser.parseComma())
3122 return true;
3124 StringRef StringValue;
3125 int64_t IntegerValue = 0;
3126 bool IsIntegerValue = true;
3128 // RISC-V attributes have a string value if the tag number is odd
3129 // and an integer value if the tag number is even.
3130 if (Tag % 2)
3131 IsIntegerValue = false;
3133 SMLoc ValueExprLoc = Parser.getTok().getLoc();
3134 if (IsIntegerValue) {
3135 const MCExpr *ValueExpr;
3136 if (Parser.parseExpression(ValueExpr))
3137 return true;
3139 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
3140 if (!CE)
3141 return Error(ValueExprLoc, "expected numeric constant");
3142 IntegerValue = CE->getValue();
3143 } else {
3144 if (Parser.getTok().isNot(AsmToken::String))
3145 return Error(Parser.getTok().getLoc(), "expected string constant");
3147 StringValue = Parser.getTok().getStringContents();
3148 Parser.Lex();
3151 if (Parser.parseEOL())
3152 return true;
3154 if (IsIntegerValue)
3155 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3156 else if (Tag != RISCVAttrs::ARCH)
3157 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3158 else {
3159 std::string Result;
3160 if (resetToArch(StringValue, ValueExprLoc, Result, false))
3161 return true;
3163 // Then emit the arch string.
3164 getTargetStreamer().emitTextAttribute(Tag, Result);
3167 return false;
3170 bool isValidInsnFormat(StringRef Format, bool AllowC) {
3171 return StringSwitch<bool>(Format)
3172 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
3173 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
3174 .Default(false);
3177 /// parseDirectiveInsn
3178 /// ::= .insn [ format encoding, (operands (, operands)*) ]
3179 /// ::= .insn [ length, value ]
3180 /// ::= .insn [ value ]
3181 bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3182 MCAsmParser &Parser = getParser();
3184 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3185 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3187 // Expect instruction format as identifier.
3188 StringRef Format;
3189 SMLoc ErrorLoc = Parser.getTok().getLoc();
3190 if (Parser.parseIdentifier(Format)) {
3191 // Try parsing .insn [ length , ] value
3192 std::optional<int64_t> Length;
3193 int64_t Value = 0;
3194 if (Parser.parseAbsoluteExpression(Value))
3195 return true;
3196 if (Parser.parseOptionalToken(AsmToken::Comma)) {
3197 Length = Value;
3198 if (Parser.parseAbsoluteExpression(Value))
3199 return true;
3201 if (*Length == 0 || (*Length % 2) != 0)
3202 return Error(ErrorLoc,
3203 "instruction lengths must be a non-zero multiple of two");
3205 // TODO: Support Instructions > 64 bits.
3206 if (*Length > 8)
3207 return Error(ErrorLoc,
3208 "instruction lengths over 64 bits are not supported");
3211 // We only derive a length from the encoding for 16- and 32-bit
3212 // instructions, as the encodings for longer instructions are not frozen in
3213 // the spec.
3214 int64_t EncodingDerivedLength = ((Value & 0b11) == 0b11) ? 4 : 2;
3216 if (Length) {
3217 // Only check the length against the encoding if the length is present and
3218 // could match
3219 if ((*Length <= 4) && (*Length != EncodingDerivedLength))
3220 return Error(ErrorLoc,
3221 "instruction length does not match the encoding");
3223 if (!isUIntN(*Length * 8, Value))
3224 return Error(ErrorLoc, "encoding value does not fit into instruction");
3225 } else {
3226 if (!isUIntN(EncodingDerivedLength * 8, Value))
3227 return Error(ErrorLoc, "encoding value does not fit into instruction");
3230 if (!AllowC && (EncodingDerivedLength == 2))
3231 return Error(ErrorLoc, "compressed instructions are not allowed");
3233 if (getParser().parseEOL("invalid operand for instruction")) {
3234 getParser().eatToEndOfStatement();
3235 return true;
3238 unsigned Opcode;
3239 if (Length) {
3240 switch (*Length) {
3241 case 2:
3242 Opcode = RISCV::Insn16;
3243 break;
3244 case 4:
3245 Opcode = RISCV::Insn32;
3246 break;
3247 case 6:
3248 Opcode = RISCV::Insn48;
3249 break;
3250 case 8:
3251 Opcode = RISCV::Insn64;
3252 break;
3253 default:
3254 llvm_unreachable("Error should have already been emitted");
3256 } else
3257 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3259 emitToStreamer(getStreamer(), MCInstBuilder(Opcode).addImm(Value));
3260 return false;
3263 if (!isValidInsnFormat(Format, AllowC))
3264 return Error(ErrorLoc, "invalid instruction format");
3266 std::string FormatName = (".insn_" + Format).str();
3268 ParseInstructionInfo Info;
3269 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
3271 if (parseInstruction(Info, FormatName, L, Operands))
3272 return true;
3274 unsigned Opcode;
3275 uint64_t ErrorInfo;
3276 return matchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3277 ErrorInfo,
3278 /*MatchingInlineAsm=*/false);
3281 /// parseDirectiveVariantCC
3282 /// ::= .variant_cc symbol
3283 bool RISCVAsmParser::parseDirectiveVariantCC() {
3284 StringRef Name;
3285 if (getParser().parseIdentifier(Name))
3286 return TokError("expected symbol name");
3287 if (parseEOL())
3288 return true;
3289 getTargetStreamer().emitDirectiveVariantCC(
3290 *getContext().getOrCreateSymbol(Name));
3291 return false;
3294 void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3295 MCInst CInst;
3296 bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
3297 if (Res)
3298 ++RISCVNumInstrsCompressed;
3299 S.emitInstruction((Res ? CInst : Inst), getSTI());
3302 void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3303 MCStreamer &Out) {
3304 SmallVector<MCInst, 8> Seq;
3305 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
3307 for (MCInst &Inst : Seq) {
3308 emitToStreamer(Out, Inst);
3312 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
3313 const MCExpr *Symbol,
3314 RISCVMCExpr::VariantKind VKHi,
3315 unsigned SecondOpcode, SMLoc IDLoc,
3316 MCStreamer &Out) {
3317 // A pair of instructions for PC-relative addressing; expands to
3318 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3319 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3320 MCContext &Ctx = getContext();
3322 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3323 Out.emitLabel(TmpLabel);
3325 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
3326 emitToStreamer(
3327 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
3329 const MCExpr *RefToLinkTmpLabel =
3330 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
3331 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
3333 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3334 .addOperand(DestReg)
3335 .addOperand(TmpReg)
3336 .addExpr(RefToLinkTmpLabel));
3339 void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3340 MCStreamer &Out) {
3341 // The load local address pseudo-instruction "lla" is used in PC-relative
3342 // addressing of local symbols:
3343 // lla rdest, symbol
3344 // expands to
3345 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3346 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3347 MCOperand DestReg = Inst.getOperand(0);
3348 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3349 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3350 RISCV::ADDI, IDLoc, Out);
3353 void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3354 MCStreamer &Out) {
3355 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3356 // addressing of global symbols:
3357 // lga rdest, symbol
3358 // expands to
3359 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3360 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3361 MCOperand DestReg = Inst.getOperand(0);
3362 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3363 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3364 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
3365 SecondOpcode, IDLoc, Out);
3368 void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3369 MCStreamer &Out) {
3370 // The load address pseudo-instruction "la" is used in PC-relative and
3371 // GOT-indirect addressing of global symbols:
3372 // la rdest, symbol
3373 // is an alias for either (for non-PIC)
3374 // lla rdest, symbol
3375 // or (for PIC)
3376 // lga rdest, symbol
3377 if (ParserOptions.IsPicEnabled)
3378 emitLoadGlobalAddress(Inst, IDLoc, Out);
3379 else
3380 emitLoadLocalAddress(Inst, IDLoc, Out);
3383 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3384 MCStreamer &Out) {
3385 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3386 // initial-exec TLS model addressing of global symbols:
3387 // la.tls.ie rdest, symbol
3388 // expands to
3389 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3390 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3391 MCOperand DestReg = Inst.getOperand(0);
3392 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3393 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3394 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
3395 SecondOpcode, IDLoc, Out);
3398 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3399 MCStreamer &Out) {
3400 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3401 // global-dynamic TLS model addressing of global symbols:
3402 // la.tls.gd rdest, symbol
3403 // expands to
3404 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3405 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3406 MCOperand DestReg = Inst.getOperand(0);
3407 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3408 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
3409 RISCV::ADDI, IDLoc, Out);
3412 void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3413 SMLoc IDLoc, MCStreamer &Out,
3414 bool HasTmpReg) {
3415 // The load/store pseudo-instruction does a pc-relative load with
3416 // a symbol.
3418 // The expansion looks like this
3420 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3421 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3422 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3423 MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
3424 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3425 MCOperand TmpReg = Inst.getOperand(0);
3426 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3427 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3428 Opcode, IDLoc, Out);
3431 void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3432 int64_t Width, SMLoc IDLoc,
3433 MCStreamer &Out) {
3434 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3435 // amounts dependent on the XLEN.
3437 // The expansion looks like this
3439 // SLLI rd, rs, XLEN - Width
3440 // SR[A|R]I rd, rd, XLEN - Width
3441 MCOperand DestReg = Inst.getOperand(0);
3442 MCOperand SourceReg = Inst.getOperand(1);
3444 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3445 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3447 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3449 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3450 .addOperand(DestReg)
3451 .addOperand(SourceReg)
3452 .addImm(ShAmt));
3454 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3455 .addOperand(DestReg)
3456 .addOperand(DestReg)
3457 .addImm(ShAmt));
3460 void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3461 MCStreamer &Out) {
3462 if (Inst.getNumOperands() == 3) {
3463 // unmasked va >= x
3465 // pseudoinstruction: vmsge{u}.vx vd, va, x
3466 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3467 emitToStreamer(Out, MCInstBuilder(Opcode)
3468 .addOperand(Inst.getOperand(0))
3469 .addOperand(Inst.getOperand(1))
3470 .addOperand(Inst.getOperand(2))
3471 .addReg(MCRegister())
3472 .setLoc(IDLoc));
3473 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3474 .addOperand(Inst.getOperand(0))
3475 .addOperand(Inst.getOperand(0))
3476 .addOperand(Inst.getOperand(0))
3477 .setLoc(IDLoc));
3478 } else if (Inst.getNumOperands() == 4) {
3479 // masked va >= x, vd != v0
3481 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3482 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3483 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3484 "The destination register should not be V0.");
3485 emitToStreamer(Out, MCInstBuilder(Opcode)
3486 .addOperand(Inst.getOperand(0))
3487 .addOperand(Inst.getOperand(1))
3488 .addOperand(Inst.getOperand(2))
3489 .addOperand(Inst.getOperand(3))
3490 .setLoc(IDLoc));
3491 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3492 .addOperand(Inst.getOperand(0))
3493 .addOperand(Inst.getOperand(0))
3494 .addReg(RISCV::V0)
3495 .setLoc(IDLoc));
3496 } else if (Inst.getNumOperands() == 5 &&
3497 Inst.getOperand(0).getReg() == RISCV::V0) {
3498 // masked va >= x, vd == v0
3500 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3501 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3502 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3503 "The destination register should be V0.");
3504 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3505 "The temporary vector register should not be V0.");
3506 emitToStreamer(Out, MCInstBuilder(Opcode)
3507 .addOperand(Inst.getOperand(1))
3508 .addOperand(Inst.getOperand(2))
3509 .addOperand(Inst.getOperand(3))
3510 .addReg(MCRegister())
3511 .setLoc(IDLoc));
3512 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3513 .addOperand(Inst.getOperand(0))
3514 .addOperand(Inst.getOperand(0))
3515 .addOperand(Inst.getOperand(1))
3516 .setLoc(IDLoc));
3517 } else if (Inst.getNumOperands() == 5) {
3518 // masked va >= x, any vd
3520 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3521 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3522 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3523 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3524 "The temporary vector register should not be V0.");
3525 emitToStreamer(Out, MCInstBuilder(Opcode)
3526 .addOperand(Inst.getOperand(1))
3527 .addOperand(Inst.getOperand(2))
3528 .addOperand(Inst.getOperand(3))
3529 .addReg(MCRegister())
3530 .setLoc(IDLoc));
3531 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3532 .addOperand(Inst.getOperand(1))
3533 .addReg(RISCV::V0)
3534 .addOperand(Inst.getOperand(1))
3535 .setLoc(IDLoc));
3536 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3537 .addOperand(Inst.getOperand(0))
3538 .addOperand(Inst.getOperand(0))
3539 .addReg(RISCV::V0)
3540 .setLoc(IDLoc));
3541 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3542 .addOperand(Inst.getOperand(0))
3543 .addOperand(Inst.getOperand(1))
3544 .addOperand(Inst.getOperand(0))
3545 .setLoc(IDLoc));
3549 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3550 OperandVector &Operands) {
3551 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
3552 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
3553 if (Inst.getOperand(2).getReg() != RISCV::X4) {
3554 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3555 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
3556 "%tprel_add modifier");
3559 return false;
3562 bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
3563 OperandVector &Operands) {
3564 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
3565 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
3566 if (Inst.getOperand(0).getReg() != RISCV::X5) {
3567 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3568 return Error(ErrorLoc, "the output operand must be t0/x5 when using "
3569 "%tlsdesc_call modifier");
3572 return false;
3575 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3576 return RISCVOperand::createReg(MCRegister(), llvm::SMLoc(), llvm::SMLoc());
3579 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3580 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3581 llvm::SMLoc());
3584 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3585 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3586 llvm::SMLoc());
3589 bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3590 OperandVector &Operands) {
3591 unsigned Opcode = Inst.getOpcode();
3593 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3594 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3595 MCRegister DestReg = Inst.getOperand(0).getReg();
3596 MCRegister TempReg = Inst.getOperand(1).getReg();
3597 if (DestReg == TempReg) {
3598 SMLoc Loc = Operands.back()->getStartLoc();
3599 return Error(Loc, "the temporary vector register cannot be the same as "
3600 "the destination register");
3604 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3605 Opcode == RISCV::TH_LWD) {
3606 MCRegister Rd1 = Inst.getOperand(0).getReg();
3607 MCRegister Rd2 = Inst.getOperand(1).getReg();
3608 MCRegister Rs1 = Inst.getOperand(2).getReg();
3609 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3610 if (Rs1 == Rd1 && Rs1 == Rd2) {
3611 SMLoc Loc = Operands[1]->getStartLoc();
3612 return Error(Loc, "rs1, rd1, and rd2 cannot all be the same");
3616 if (Opcode == RISCV::CM_MVSA01) {
3617 MCRegister Rd1 = Inst.getOperand(0).getReg();
3618 MCRegister Rd2 = Inst.getOperand(1).getReg();
3619 if (Rd1 == Rd2) {
3620 SMLoc Loc = Operands[1]->getStartLoc();
3621 return Error(Loc, "rs1 and rs2 must be different");
3625 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3626 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3627 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3628 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3629 // depending on the data width.
3630 if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
3631 SMLoc Loc = Operands.back()->getStartLoc();
3632 return Error(Loc, "operand must be constant 3");
3633 } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
3634 SMLoc Loc = Operands.back()->getStartLoc();
3635 return Error(Loc, "operand must be constant 4");
3638 const MCInstrDesc &MCID = MII.get(Opcode);
3639 if (!(MCID.TSFlags & RISCVII::ConstraintMask))
3640 return false;
3642 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3643 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3644 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3645 MCRegister VCIXDst = Inst.getOperand(0).getReg();
3646 SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
3647 if (MCID.TSFlags & RISCVII::VS1Constraint) {
3648 MCRegister VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3649 if (VCIXDst == VCIXRs1)
3650 return Error(VCIXDstLoc, "the destination vector register group cannot"
3651 " overlap the source vector register group");
3653 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3654 MCRegister VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
3655 if (VCIXDst == VCIXRs2)
3656 return Error(VCIXDstLoc, "the destination vector register group cannot"
3657 " overlap the source vector register group");
3659 return false;
3662 MCRegister DestReg = Inst.getOperand(0).getReg();
3663 unsigned Offset = 0;
3664 int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
3665 if (TiedOp == 0)
3666 Offset = 1;
3668 // Operands[1] will be the first operand, DestReg.
3669 SMLoc Loc = Operands[1]->getStartLoc();
3670 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3671 MCRegister CheckReg = Inst.getOperand(Offset + 1).getReg();
3672 if (DestReg == CheckReg)
3673 return Error(Loc, "the destination vector register group cannot overlap"
3674 " the source vector register group");
3676 if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
3677 MCRegister CheckReg = Inst.getOperand(Offset + 2).getReg();
3678 if (DestReg == CheckReg)
3679 return Error(Loc, "the destination vector register group cannot overlap"
3680 " the source vector register group");
3682 if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3683 // vadc, vsbc are special cases. These instructions have no mask register.
3684 // The destination register could not be V0.
3685 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3686 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3687 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3688 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3689 Opcode == RISCV::VMERGE_VXM)
3690 return Error(Loc, "the destination vector register group cannot be V0");
3692 // Regardless masked or unmasked version, the number of operands is the
3693 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3694 // actually. We need to check the last operand to ensure whether it is
3695 // masked or not.
3696 MCRegister CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3697 assert((CheckReg == RISCV::V0 || !CheckReg) &&
3698 "Unexpected register for mask operand");
3700 if (DestReg == CheckReg)
3701 return Error(Loc, "the destination vector register group cannot overlap"
3702 " the mask register");
3704 return false;
3707 bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
3708 OperandVector &Operands,
3709 MCStreamer &Out) {
3710 Inst.setLoc(IDLoc);
3712 switch (Inst.getOpcode()) {
3713 default:
3714 break;
3715 case RISCV::PseudoC_ADDI_NOP:
3716 emitToStreamer(Out, MCInstBuilder(RISCV::C_NOP));
3717 return false;
3718 case RISCV::PseudoLLAImm:
3719 case RISCV::PseudoLAImm:
3720 case RISCV::PseudoLI: {
3721 MCRegister Reg = Inst.getOperand(0).getReg();
3722 const MCOperand &Op1 = Inst.getOperand(1);
3723 if (Op1.isExpr()) {
3724 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3725 // Just convert to an addi. This allows compatibility with gas.
3726 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
3727 .addReg(Reg)
3728 .addReg(RISCV::X0)
3729 .addExpr(Op1.getExpr()));
3730 return false;
3732 int64_t Imm = Inst.getOperand(1).getImm();
3733 // On RV32 the immediate here can either be a signed or an unsigned
3734 // 32-bit number. Sign extension has to be performed to ensure that Imm
3735 // represents the expected signed 64-bit number.
3736 if (!isRV64())
3737 Imm = SignExtend64<32>(Imm);
3738 emitLoadImm(Reg, Imm, Out);
3739 return false;
3741 case RISCV::PseudoLLA:
3742 emitLoadLocalAddress(Inst, IDLoc, Out);
3743 return false;
3744 case RISCV::PseudoLGA:
3745 emitLoadGlobalAddress(Inst, IDLoc, Out);
3746 return false;
3747 case RISCV::PseudoLA:
3748 emitLoadAddress(Inst, IDLoc, Out);
3749 return false;
3750 case RISCV::PseudoLA_TLS_IE:
3751 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3752 return false;
3753 case RISCV::PseudoLA_TLS_GD:
3754 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3755 return false;
3756 case RISCV::PseudoLB:
3757 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
3758 return false;
3759 case RISCV::PseudoLBU:
3760 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
3761 return false;
3762 case RISCV::PseudoLH:
3763 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
3764 return false;
3765 case RISCV::PseudoLHU:
3766 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
3767 return false;
3768 case RISCV::PseudoLW:
3769 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
3770 return false;
3771 case RISCV::PseudoLWU:
3772 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
3773 return false;
3774 case RISCV::PseudoLD:
3775 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
3776 return false;
3777 case RISCV::PseudoFLH:
3778 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3779 return false;
3780 case RISCV::PseudoFLW:
3781 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
3782 return false;
3783 case RISCV::PseudoFLD:
3784 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
3785 return false;
3786 case RISCV::PseudoSB:
3787 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
3788 return false;
3789 case RISCV::PseudoSH:
3790 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
3791 return false;
3792 case RISCV::PseudoSW:
3793 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
3794 return false;
3795 case RISCV::PseudoSD:
3796 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
3797 return false;
3798 case RISCV::PseudoFSH:
3799 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3800 return false;
3801 case RISCV::PseudoFSW:
3802 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
3803 return false;
3804 case RISCV::PseudoFSD:
3805 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
3806 return false;
3807 case RISCV::PseudoAddTPRel:
3808 if (checkPseudoAddTPRel(Inst, Operands))
3809 return true;
3810 break;
3811 case RISCV::PseudoTLSDESCCall:
3812 if (checkPseudoTLSDESCCall(Inst, Operands))
3813 return true;
3814 break;
3815 case RISCV::PseudoSEXT_B:
3816 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3817 return false;
3818 case RISCV::PseudoSEXT_H:
3819 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3820 return false;
3821 case RISCV::PseudoZEXT_H:
3822 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3823 return false;
3824 case RISCV::PseudoZEXT_W:
3825 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3826 return false;
3827 case RISCV::PseudoVMSGEU_VX:
3828 case RISCV::PseudoVMSGEU_VX_M:
3829 case RISCV::PseudoVMSGEU_VX_M_T:
3830 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3831 return false;
3832 case RISCV::PseudoVMSGE_VX:
3833 case RISCV::PseudoVMSGE_VX_M:
3834 case RISCV::PseudoVMSGE_VX_M_T:
3835 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3836 return false;
3837 case RISCV::PseudoVMSGE_VI:
3838 case RISCV::PseudoVMSLT_VI: {
3839 // These instructions are signed and so is immediate so we can subtract one
3840 // and change the opcode.
3841 int64_t Imm = Inst.getOperand(2).getImm();
3842 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3843 : RISCV::VMSLE_VI;
3844 emitToStreamer(Out, MCInstBuilder(Opc)
3845 .addOperand(Inst.getOperand(0))
3846 .addOperand(Inst.getOperand(1))
3847 .addImm(Imm - 1)
3848 .addOperand(Inst.getOperand(3))
3849 .setLoc(IDLoc));
3850 return false;
3852 case RISCV::PseudoVMSGEU_VI:
3853 case RISCV::PseudoVMSLTU_VI: {
3854 int64_t Imm = Inst.getOperand(2).getImm();
3855 // Unsigned comparisons are tricky because the immediate is signed. If the
3856 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3857 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3858 // vmsne v0, v1, v1 which is always false.
3859 if (Imm == 0) {
3860 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3861 ? RISCV::VMSEQ_VV
3862 : RISCV::VMSNE_VV;
3863 emitToStreamer(Out, MCInstBuilder(Opc)
3864 .addOperand(Inst.getOperand(0))
3865 .addOperand(Inst.getOperand(1))
3866 .addOperand(Inst.getOperand(1))
3867 .addOperand(Inst.getOperand(3))
3868 .setLoc(IDLoc));
3869 } else {
3870 // Other immediate values can subtract one like signed.
3871 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3872 ? RISCV::VMSGTU_VI
3873 : RISCV::VMSLEU_VI;
3874 emitToStreamer(Out, MCInstBuilder(Opc)
3875 .addOperand(Inst.getOperand(0))
3876 .addOperand(Inst.getOperand(1))
3877 .addImm(Imm - 1)
3878 .addOperand(Inst.getOperand(3))
3879 .setLoc(IDLoc));
3882 return false;
3886 emitToStreamer(Out, Inst);
3887 return false;
3890 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() {
3891 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
3892 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());