LLVM 24.0.0git
RISCVAsmParser.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
17#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/SmallSet.h"
21#include "llvm/ADT/Statistic.h"
23#include "llvm/MC/MCAssembler.h"
24#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
28#include "llvm/MC/MCInstrInfo.h"
34#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCValue.h"
41#include "llvm/Support/Debug.h"
45
46#include <limits>
47#include <map>
48#include <optional>
49
50using namespace llvm;
51
52#define DEBUG_TYPE "riscv-asm-parser"
53
54STATISTIC(RISCVNumInstrsCompressed,
55 "Number of RISC-V Compressed instructions emitted");
56
57static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",
58 cl::init(false));
59
60namespace {
61struct RISCVOperand;
62
63struct ParserOptionsSet {
64 bool IsPicEnabled;
65};
66
67class RISCVAsmParser : public MCTargetAsmParser {
68 // This tracks the parsing of the 4 optional operands that make up the vtype
69 // portion of vset(i)vli instructions which are separated by commas.
70 enum class VTypeState {
71 SeenNothingYet,
72 SeenSew,
73 SeenLmul,
74 SeenTailPolicy,
75 SeenMaskPolicy,
76 };
77
78 SmallVector<FeatureBitset, 4> FeatureBitStack;
79
80 SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
81 ParserOptionsSet ParserOptions;
82
83 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
84 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
85 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); }
86 bool enableExperimentalExtension() const {
87 return getSTI().hasFeature(RISCV::Experimental);
88 }
89
90 RISCVTargetStreamer &getTargetStreamer() {
91 assert(getParser().getStreamer().getTargetStreamer() &&
92 "do not have a target streamer");
93 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
94 return static_cast<RISCVTargetStreamer &>(TS);
95 }
96
97 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
98 unsigned Kind) override;
99
100 bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
101 const Twine &Msg);
102
103 struct NearMissMessage {
104 SMLoc Loc;
105 std::string Message;
106 };
107
108 std::string getCustomOperandDiag(unsigned MatchError);
109
110 void FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn,
111 SmallVectorImpl<NearMissMessage> &NearMissesOut,
112 SMLoc IDLoc, OperandVector &Operands);
113 void ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses, SMLoc IDLoc,
115
116 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
117 OperandVector &Operands, MCStreamer &Out,
118 uint64_t &ErrorInfo,
119 bool MatchingInlineAsm) override;
120
121 MCRegister matchRegisterNameHelper(StringRef Name) const;
122 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
123 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
124 SMLoc &EndLoc) override;
125
126 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
127 SMLoc NameLoc, OperandVector &Operands) override;
128
129 ParseStatus parseDirective(AsmToken DirectiveID) override;
130
131 bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew,
132 unsigned &Lmul, bool &Fractional, bool &TailAgnostic,
133 bool &MaskAgnostic, bool &AltFmt);
134 bool generateVTypeError(SMLoc ErrorLoc);
135
136 bool generateXSfmmVTypeError(SMLoc ErrorLoc);
137 // Helper to actually emit an instruction to the MCStreamer. Also, when
138 // possible, compression of the instruction is performed.
139 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
140
141 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
142 // synthesize the desired immediate value into the destination register.
143 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
144
145 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
146 // helpers such as emitLoadLocalAddress and emitLoadAddress.
147 void emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,
148 const MCExpr *Symbol, RISCV::Specifier VKHi,
149 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
150
151 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
152 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
153
154 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
155 void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
156
157 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
158 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
159
160 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
161 // addressing.
162 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
163
164 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
165 // addressing.
166 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
167
168 // Helper to emit pseudo load/store instruction with a symbol.
169 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
170 MCStreamer &Out, bool HasTmpReg);
171
172 // Helper to emit Xqcilo pseudo load/store as qc.e.li + PseudoQCAccess pair.
173 // For loads: qc.e.li rd, sym; lx rd, 0(rd), %qc.access(sym)
174 // For stores: qc.e.li rt, sym; sx rs, 0(rt), %qc.access(sym)
175 void emitQCELILoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
176 MCStreamer &Out, bool HasTmpReg);
177
178 // Helper to emit pseudo sign/zero extend instruction.
179 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
180 SMLoc IDLoc, MCStreamer &Out);
181
182 // Helper to emit pseudo vmsge{u}.vx instruction.
183 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
184
185 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
186 // Enforcing this using a restricted register class for the second input
187 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
188 // 'add' is an overloaded mnemonic.
189 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
190
191 // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
192 // Enforcing this using a restricted register class for the output
193 // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
194 // 'jalr' is an overloaded mnemonic.
195 bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);
196
197 // Check instruction constraints.
198 bool validateInstruction(MCInst &Inst, OperandVector &Operands);
199
200 /// Helper for processing MC instructions that have been successfully matched
201 /// by matchAndEmitInstruction. Modifications to the emitted instructions,
202 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
203 /// in this method.
204 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
205 MCStreamer &Out);
206
207// Auto-generated instruction matching functions
208#define GET_ASSEMBLER_HEADER
209#include "RISCVGenAsmMatcher.inc"
210
211 ParseStatus parseCSRSystemRegister(OperandVector &Operands);
213 ParseStatus parseExpression(OperandVector &Operands);
214 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
215 ParseStatus parseMemOpBaseReg(OperandVector &Operands);
216 ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
217 ParseStatus parseOperandWithSpecifier(OperandVector &Operands);
218 ParseStatus parseBareSymbol(OperandVector &Operands);
219 ParseStatus parseCallSymbol(OperandVector &Operands);
220 ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);
221 ParseStatus parseJALOffset(OperandVector &Operands);
222 ParseStatus parseVTypeI(OperandVector &Operands);
223 ParseStatus parseMaskReg(OperandVector &Operands);
224 ParseStatus parseVScaleReg(OperandVector &Operands);
225 ParseStatus parseTileLambda(OperandVector &Operands);
226 ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
227 ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
228 ParseStatus parseGPRAsFPR(OperandVector &Operands);
229 ParseStatus parseGPRAsFPR64(OperandVector &Operands);
230 ParseStatus parseGPRPairAsFPR64(OperandVector &Operands);
231 template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands);
232 ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
233 ParseStatus parseFRMArg(OperandVector &Operands);
234 ParseStatus parseSMTVType(OperandVector &Operands);
235 ParseStatus parseFenceArg(OperandVector &Operands);
236 ParseStatus parseRegList(OperandVector &Operands, bool MustIncludeS0 = false);
237 ParseStatus parseRegListS0(OperandVector &Operands) {
238 return parseRegList(Operands, /*MustIncludeS0=*/true);
239 }
240
241 ParseStatus parseRegReg(OperandVector &Operands);
242 ParseStatus parseXSfmmVType(OperandVector &Operands);
243 ParseStatus parseZcmpStackAdj(OperandVector &Operands,
244 bool ExpectNegative = false);
245 ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {
246 return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);
247 }
248
249 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
250 bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);
251 bool parseDataExpr(const MCExpr *&Res) override;
252
253 bool parseDirectiveOption();
254 bool parseDirectiveAttribute();
255 bool parseDirectiveInsn(SMLoc L);
256 bool parseDirectiveVariantCC();
257
258 /// Helper to reset target features for a new arch string. It
259 /// also records the new arch string that is expanded by RISCVISAInfo
260 /// and reports error for invalid arch string.
261 bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
262 bool FromOptionDirective);
263
264 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
265 if (!(getSTI().hasFeature(Feature))) {
266 MCSubtargetInfo &STI = copySTI();
267 STI.ToggleFeature(FeatureString);
268
269 // Update the C and Zce implications.
271
272 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
273 }
274 }
275
276 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
277 if (getSTI().hasFeature(Feature)) {
278 MCSubtargetInfo &STI = copySTI();
279 setAvailableFeatures(
280 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
281 }
282 }
283
284 void pushFeatureBits() {
285 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
286 "These two stacks must be kept synchronized");
287 FeatureBitStack.push_back(getSTI().getFeatureBits());
288 ParserOptionsStack.push_back(ParserOptions);
289 }
290
291 bool popFeatureBits() {
292 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
293 "These two stacks must be kept synchronized");
294 if (FeatureBitStack.empty())
295 return true;
296
297 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
298 copySTI().setFeatureBits(FeatureBits);
299 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
300
301 ParserOptions = ParserOptionsStack.pop_back_val();
302
303 return false;
304 }
305
306 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
307 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
308 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
309 std::unique_ptr<RISCVOperand> defaultSMTVType();
310 std::unique_ptr<RISCVOperand> defaultZeroOffset();
311
312public:
313 enum RISCVMatchResultTy : unsigned {
314 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
315#define GET_OPERAND_DIAGNOSTIC_TYPES
316#include "RISCVGenAsmMatcher.inc"
317#undef GET_OPERAND_DIAGNOSTIC_TYPES
318 };
319
320 static bool classifySymbolRef(const MCExpr *Expr, RISCV::Specifier &Kind);
321 static bool isSymbolDiff(const MCExpr *Expr);
322
323 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
324 const MCInstrInfo &MII)
325 : MCTargetAsmParser(STI, MII) {
327
328 Parser.addAliasForDirective(".half", ".2byte");
329 Parser.addAliasForDirective(".hword", ".2byte");
330 Parser.addAliasForDirective(".word", ".4byte");
331 Parser.addAliasForDirective(".dword", ".8byte");
332 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
333
334 auto ABIName = StringRef(getTargetOptions().ABIName);
335 if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
336 errs() << "Hard-float 'f' ABI can't be used for a target that "
337 "doesn't support the F instruction set extension (ignoring "
338 "target-abi)\n";
339 } else if (ABIName.ends_with("d") &&
340 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
341 errs() << "Hard-float 'd' ABI can't be used for a target that "
342 "doesn't support the D instruction set extension (ignoring "
343 "target-abi)\n";
344 }
345
346 // Use computeTargetABI to check if ABIName is valid. If invalid, output
347 // error message.
348 RISCVABI::computeTargetABI(STI, ABIName);
349
350 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
351 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
352
354 getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
355 }
356};
357
358/// RISCVOperand - Instances of this class represent a parsed machine
359/// instruction
360struct RISCVOperand final : public MCParsedAsmOperand {
361
362 enum class KindTy {
363 Token,
364 Register,
365 Expression,
366 FPImmediate,
367 SystemRegister,
368 VType,
369 SMTVType,
370 FRM,
371 Fence,
372 RegList,
373 StackAdj,
374 RegReg,
375 } Kind;
376
377 struct RegOp {
378 MCRegister Reg;
379 bool IsGPRAsFPR;
380 };
381
382 struct ExprOp {
383 const MCExpr *Expr;
384 bool IsRV64;
385 };
386
387 struct FPImmOp {
388 uint64_t Val;
389 };
390
391 struct SysRegOp {
392 const char *Data;
393 unsigned Length;
394 unsigned Encoding;
395 // FIXME: Add the Encoding parsed fields as needed for checks,
396 // e.g.: read/write or user/supervisor/machine privileges.
397 };
398
399 struct VTypeOp {
400 unsigned Val;
401 };
402
403 struct SMTVTypeOp {
405 };
406
407 struct FRMOp {
409 };
410
411 struct FenceOp {
412 unsigned Val;
413 };
414
415 struct RegListOp {
416 unsigned Encoding;
417 };
418
419 struct StackAdjOp {
420 unsigned Val;
421 };
422
423 struct RegRegOp {
424 MCRegister BaseReg;
425 MCRegister OffsetReg;
426 };
427
428 SMLoc StartLoc, EndLoc;
429 union {
430 StringRef Tok;
431 RegOp Reg;
432 ExprOp Expr;
433 FPImmOp FPImm;
434 SysRegOp SysReg;
435 VTypeOp VType;
436 SMTVTypeOp SMTVType;
437 FRMOp FRM;
438 FenceOp Fence;
439 RegListOp RegList;
440 StackAdjOp StackAdj;
441 RegRegOp RegReg;
442 };
443
444 RISCVOperand(KindTy K) : Kind(K) {}
445
446public:
447 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
448 Kind = o.Kind;
449 StartLoc = o.StartLoc;
450 EndLoc = o.EndLoc;
451 switch (Kind) {
452 case KindTy::Register:
453 Reg = o.Reg;
454 break;
455 case KindTy::Expression:
456 Expr = o.Expr;
457 break;
458 case KindTy::FPImmediate:
459 FPImm = o.FPImm;
460 break;
461 case KindTy::Token:
462 Tok = o.Tok;
463 break;
464 case KindTy::SystemRegister:
465 SysReg = o.SysReg;
466 break;
467 case KindTy::VType:
468 VType = o.VType;
469 break;
470 case KindTy::SMTVType:
471 SMTVType = o.SMTVType;
472 break;
473 case KindTy::FRM:
474 FRM = o.FRM;
475 break;
476 case KindTy::Fence:
477 Fence = o.Fence;
478 break;
479 case KindTy::RegList:
480 RegList = o.RegList;
481 break;
482 case KindTy::StackAdj:
483 StackAdj = o.StackAdj;
484 break;
485 case KindTy::RegReg:
486 RegReg = o.RegReg;
487 break;
488 }
489 }
490
491 bool isToken() const override { return Kind == KindTy::Token; }
492 bool isReg() const override { return Kind == KindTy::Register; }
493 bool isExpr() const { return Kind == KindTy::Expression; }
494 bool isV0Reg() const {
495 return Kind == KindTy::Register && Reg.Reg == RISCV::V0;
496 }
497 bool isAnyReg() const {
498 return Kind == KindTy::Register &&
499 (getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg.Reg) ||
500 getRISCVMCRegisterClass(RISCV::FPR64RegClassID).contains(Reg.Reg) ||
501 getRISCVMCRegisterClass(RISCV::VRRegClassID).contains(Reg.Reg));
502 }
503 bool isAnyRegC() const {
504 return Kind == KindTy::Register &&
505 (getRISCVMCRegisterClass(RISCV::GPRCRegClassID).contains(Reg.Reg) ||
506 getRISCVMCRegisterClass(RISCV::FPR64CRegClassID).contains(Reg.Reg));
507 }
508 bool isImm() const override { return isExpr(); }
509 bool isMem() const override { return false; }
510 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
511 bool isRegReg() const { return Kind == KindTy::RegReg; }
512 bool isRegList() const { return Kind == KindTy::RegList; }
513 bool isRegListS0() const {
514 return Kind == KindTy::RegList && RegList.Encoding != RISCVZC::RA;
515 }
516 bool isStackAdj() const { return Kind == KindTy::StackAdj; }
517
518 bool isGPR() const {
519 return Kind == KindTy::Register &&
520 getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg.Reg);
521 }
522
523 bool isYGPR() const {
524 return Kind == KindTy::Register &&
525 getRISCVMCRegisterClass(RISCV::YGPRRegClassID).contains(Reg.Reg);
526 }
527
528 bool isGPRPair() const {
529 return Kind == KindTy::Register &&
530 getRISCVMCRegisterClass(RISCV::GPRPairRegClassID).contains(Reg.Reg);
531 }
532
533 bool isGPRPairC() const {
534 return Kind == KindTy::Register &&
535 getRISCVMCRegisterClass(RISCV::GPRPairCRegClassID).contains(Reg.Reg);
536 }
537
538 bool isGPRPairNoX0() const {
539 return Kind == KindTy::Register &&
540 getRISCVMCRegisterClass(RISCV::GPRPairNoX0RegClassID)
541 .contains(Reg.Reg);
542 }
543
544 bool isGPRF16() const {
545 return Kind == KindTy::Register &&
546 getRISCVMCRegisterClass(RISCV::GPRF16RegClassID).contains(Reg.Reg);
547 }
548
549 bool isGPRF32() const {
550 return Kind == KindTy::Register &&
551 getRISCVMCRegisterClass(RISCV::GPRF32RegClassID).contains(Reg.Reg);
552 }
553
554 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
555 bool isGPRAsFPR16() const { return isGPRF16() && Reg.IsGPRAsFPR; }
556 bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
557 bool isGPRPairAsFPR64() const { return isGPRPair() && Reg.IsGPRAsFPR; }
558
559 static bool evaluateConstantExpr(const MCExpr *Expr, int64_t &Imm) {
560 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
561 Imm = CE->getValue();
562 return true;
563 }
564
565 return false;
566 }
567
568 // True if operand is a symbol with no modifiers, or a constant with no
569 // modifiers and isShiftedInt<N-1, 1>(Op).
570 template <int N> bool isBareSimmNLsb0() const {
571 if (!isExpr())
572 return false;
573
574 int64_t Imm;
575 if (evaluateConstantExpr(getExpr(), Imm))
576 return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, isRV64Expr()));
577
579 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
580 VK == RISCV::S_None;
581 }
582
583 // True if operand is a symbol with no modifiers, or a constant with no
584 // modifiers and isInt<N>(Op).
585 template <int N> bool isBareSimmN() const {
586 if (!isExpr())
587 return false;
588
589 int64_t Imm;
590 if (evaluateConstantExpr(getExpr(), Imm))
591 return isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));
592
594 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
595 VK == RISCV::S_None;
596 }
597
598 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
599
600 bool isBareSymbol() const {
601 int64_t Imm;
602 // Must be of 'immediate' type but not a constant.
603 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
604 return false;
605
607 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
608 VK == RISCV::S_None;
609 }
610
611 bool isCallSymbol() const {
612 int64_t Imm;
613 // Must be of 'immediate' type but not a constant.
614 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
615 return false;
616
618 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
619 VK == RISCV::S_CALL_PLT;
620 }
621
622 bool isPseudoJumpSymbol() const {
623 int64_t Imm;
624 // Must be of 'immediate' type but not a constant.
625 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
626 return false;
627
629 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
630 VK == RISCV::S_CALL_PLT;
631 }
632
633 bool isTPRelAddSymbol() const {
634 int64_t Imm;
635 // Must be of 'immediate' type but not a constant.
636 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
637 return false;
638
640 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
641 VK == ELF::R_RISCV_TPREL_ADD;
642 }
643
644 bool isTLSDESCCallSymbol() const {
645 int64_t Imm;
646 // Must be of 'immediate' type but not a constant.
647 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
648 return false;
649
651 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
652 VK == ELF::R_RISCV_TLSDESC_CALL;
653 }
654
655 bool isQCAccessSymbol() const {
656 int64_t Imm;
657 // Must be of 'immediate' type but not a constant.
658 if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
659 return false;
660
662 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
663 VK == RISCV::S_QC_ACCESS;
664 }
665
666 bool isCSRSystemRegister() const { return isSystemRegister(); }
667
668 // If the last operand of the vsetvli/vsetvli instruction is a constant
669 // expression, KindTy is Immediate.
670 bool isVTypeI10() const {
671 if (Kind == KindTy::VType)
672 return true;
673 return isUImm<10>();
674 }
675 bool isVTypeI11() const {
676 if (Kind == KindTy::VType)
677 return true;
678 return isUImm<11>();
679 }
680
681 bool isXSfmmVType() const {
682 return Kind == KindTy::VType && RISCVVType::isValidXSfmmVType(VType.Val);
683 }
684
685 bool isTileLambda() const {
686 return isUImmPred([](int64_t Imm) { return Imm && isUInt<3>(Imm); });
687 }
688
689 /// Return true if the operand is a valid for the fence instruction e.g.
690 /// ('iorw').
691 bool isFenceArg() const { return Kind == KindTy::Fence; }
692
693 /// Return true if the operand is a valid floating point rounding mode.
694 bool isFRMArg() const { return Kind == KindTy::FRM; }
695 bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }
696 bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
697
698 // Return true if the operand is a valid SpacemiT's Integer Matrix
699 // VType(i4/i8).
700 bool isSMTVType() const {
701 return Kind == KindTy::SMTVType &&
702 XSMTVTypeMode::isValidSMTVTypeMode(SMTVType.SMTVType);
703 }
704
705 bool isSMTI8() const {
706 return isSMTVType() && SMTVType.SMTVType == XSMTVTypeMode::SMT_I8;
707 }
708
709 /// Return true if the operand is a valid fli.s floating-point immediate.
710 bool isLoadFPImm() const {
711 if (isExpr())
712 return isUImm5();
713 if (Kind != KindTy::FPImmediate)
714 return false;
716 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
717 // Don't allow decimal version of the minimum value. It is a different value
718 // for each supported data type.
719 return Idx >= 0 && Idx != 1;
720 }
721
722 bool isImmXLenLI() const {
723 int64_t Imm;
724 if (!isExpr())
725 return false;
726 // Given only Imm, ensuring that the actually specified constant is either
727 // a signed or unsigned 64-bit number is unfortunately impossible.
728 if (evaluateConstantExpr(getExpr(), Imm))
729 return isRV64Expr() || (isInt<32>(Imm) || isUInt<32>(Imm));
730
731 return RISCVAsmParser::isSymbolDiff(getExpr());
732 }
733
734 bool isImmXLenLI_Restricted() const {
735 int64_t Imm;
736 if (!isExpr())
737 return false;
738 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
739 // 'la imm' supports constant immediates only.
740 return IsConstantImm &&
741 (isRV64Expr() || (isInt<32>(Imm) || isUInt<32>(Imm)));
742 }
743
744 template <unsigned N> bool isUImm() const {
745 int64_t Imm;
746 if (!isExpr())
747 return false;
748 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
749 return IsConstantImm && isUInt<N>(Imm);
750 }
751
752 template <unsigned N, unsigned S> bool isUImmShifted() const {
753 int64_t Imm;
754 if (!isExpr())
755 return false;
756 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
757 return IsConstantImm && isShiftedUInt<N, S>(Imm);
758 }
759
760 template <class Pred> bool isUImmPred(Pred p) const {
761 int64_t Imm;
762 if (!isExpr())
763 return false;
764 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
765 return IsConstantImm && p(Imm);
766 }
767
768 bool isUImmLog2XLen() const {
769 if (isExpr() && isRV64Expr())
770 return isUImm<6>();
771 return isUImm<5>();
772 }
773
774 bool isUImmLog2XLenNonZero() const {
775 if (isExpr() && isRV64Expr())
776 return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<6>(Imm); });
777 return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });
778 }
779
780 bool isUImmLog2XLenHalf() const {
781 if (isExpr() && isRV64Expr())
782 return isUImm<5>();
783 return isUImm<4>();
784 }
785
786 bool isUImm1() const { return isUImm<1>(); }
787 bool isUImm2() const { return isUImm<2>(); }
788 bool isUImm3() const { return isUImm<3>(); }
789 bool isUImm4() const { return isUImm<4>(); }
790 bool isUImm5() const { return isUImm<5>(); }
791 bool isUImm6() const { return isUImm<6>(); }
792 bool isUImm7() const { return isUImm<7>(); }
793 bool isUImm8() const { return isUImm<8>(); }
794 bool isUImm9() const { return isUImm<9>(); }
795 bool isUImm10() const { return isUImm<10>(); }
796 bool isUImm11() const { return isUImm<11>(); }
797 bool isUImm16() const { return isUImm<16>(); }
798 bool isUImm20() const { return isUImm<20>(); }
799 bool isUImm32() const { return isUImm<32>(); }
800 bool isUImm48() const { return isUImm<48>(); }
801 bool isUImm64() const { return isUImm<64>(); }
802
803 bool isUImm5NonZero() const {
804 return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });
805 }
806
807 bool isUImm5GT3() const {
808 return isUImmPred([](int64_t Imm) { return isUInt<5>(Imm) && Imm > 3; });
809 }
810
811 bool isUImm4Plus1() const {
812 return isUImmPred(
813 [](int64_t Imm) { return Imm > 0 && isUInt<4>(Imm - 1); });
814 }
815
816 bool isUImm5Plus1() const {
817 return isUImmPred(
818 [](int64_t Imm) { return Imm > 0 && isUInt<5>(Imm - 1); });
819 }
820
821 bool isUImm6Plus1() const {
822 return isUImmPred(
823 [](int64_t Imm) { return Imm > 0 && isUInt<6>(Imm - 1); });
824 }
825
826 bool isUImm5GE6Plus1() const {
827 return isUImmPred(
828 [](int64_t Imm) { return Imm >= 6 && isUInt<5>(Imm - 1); });
829 }
830
831 bool isUImm5Slist() const {
832 return isUImmPred([](int64_t Imm) {
833 return (Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
834 (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31);
835 });
836 }
837
838 bool isUImm7EqXLen() const {
839 return isUImmPred(
840 [this](int64_t Imm) { return isRV64Expr() ? Imm == 64 : Imm == 32; });
841 }
842
843 bool isUImm8GE32() const {
844 return isUImmPred([](int64_t Imm) { return isUInt<8>(Imm) && Imm >= 32; });
845 }
846
847 bool isRnumArg() const {
848 return isUImmPred(
849 [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(10); });
850 }
851
852 bool isRnumArg_0_7() const {
853 return isUImmPred(
854 [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(7); });
855 }
856
857 bool isRnumArg_1_10() const {
858 return isUImmPred(
859 [](int64_t Imm) { return Imm >= INT64_C(1) && Imm <= INT64_C(10); });
860 }
861
862 bool isRnumArg_2_14() const {
863 return isUImmPred(
864 [](int64_t Imm) { return Imm >= INT64_C(2) && Imm <= INT64_C(14); });
865 }
866
867 template <unsigned N> bool isSImm() const {
868 int64_t Imm;
869 if (!isExpr())
870 return false;
871 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
872 return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));
873 }
874
875 bool isYBNDSWImm() const {
876 if (!isExpr())
877 return false;
878
879 int64_t Imm;
880 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
881 return IsConstantImm && RISCV::isValidYBNDSWImm(Imm);
882 }
883
884 template <class Pred> bool isSImmPred(Pred p) const {
885 int64_t Imm;
886 if (!isExpr())
887 return false;
888 bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
889 return IsConstantImm && p(fixImmediateForRV32(Imm, isRV64Expr()));
890 }
891
892 bool isSImm5() const { return isSImm<5>(); }
893 bool isSImm6() const { return isSImm<6>(); }
894 bool isSImm10() const { return isSImm<10>(); }
895 bool isSImm11() const { return isSImm<11>(); }
896 bool isSImm12() const { return isSImm<12>(); }
897 bool isSImm16() const { return isSImm<16>(); }
898 bool isSImm26() const { return isSImm<26>(); }
899
900 bool isSImm5NonZero() const {
901 return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<5>(Imm); });
902 }
903
904 bool isSImm6NonZero() const {
905 return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<6>(Imm); });
906 }
907
908 bool isCLUIImm() const {
909 return isUImmPred([](int64_t Imm) {
910 return (isUInt<5>(Imm) && Imm != 0) || (Imm >= 0xfffe0 && Imm <= 0xfffff);
911 });
912 }
913
914 bool isUImm2Lsb0() const { return isUImmShifted<1, 1>(); }
915
916 bool isUImm5Lsb0() const { return isUImmShifted<4, 1>(); }
917
918 bool isUImm6Lsb0() const { return isUImmShifted<5, 1>(); }
919
920 bool isUImm6Lsb000() const { return isUImmShifted<3, 3>(); }
921
922 bool isUImm7Lsb00() const { return isUImmShifted<5, 2>(); }
923
924 bool isUImm7Lsb000() const { return isUImmShifted<4, 3>(); }
925
926 bool isUImm8Lsb00() const { return isUImmShifted<6, 2>(); }
927
928 bool isUImm8Lsb000() const { return isUImmShifted<5, 3>(); }
929
930 bool isUImm9Lsb000() const { return isUImmShifted<6, 3>(); }
931
932 bool isUImm14Lsb00() const { return isUImmShifted<12, 2>(); }
933
934 bool isUImm10Lsb00NonZero() const {
935 return isUImmPred(
936 [](int64_t Imm) { return isShiftedUInt<8, 2>(Imm) && (Imm != 0); });
937 }
938
939 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
940 // This allows writing 'addi a0, a0, 0xffffffff'.
941 static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
942 if (IsRV64Imm || !isUInt<32>(Imm))
943 return Imm;
944 return SignExtend64<32>(Imm);
945 }
946
947 bool isSImm12LO() const {
948 if (!isExpr())
949 return false;
950
951 int64_t Imm;
952 if (evaluateConstantExpr(getExpr(), Imm))
953 return isInt<12>(fixImmediateForRV32(Imm, isRV64Expr()));
954
956 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
957 (VK == RISCV::S_LO || VK == RISCV::S_PCREL_LO ||
958 VK == RISCV::S_TPREL_LO || VK == ELF::R_RISCV_TLSDESC_LOAD_LO12 ||
959 VK == ELF::R_RISCV_TLSDESC_ADD_LO12);
960 }
961
962 /// Returns NoMatch rather than the NearMatch of the underlying predicate
963 /// for anything that is not an immediate at all (such as the '(' token of an
964 /// offset-less memory operand). This lets the matcher skip this optional
965 /// operand and insert the default 0 offset. An immediate that fails Pred
966 /// (e.g. out of range) still reports the wrapped class diagnostic.
967 template <bool (RISCVOperand::*Pred)() const>
968 DiagnosticPredicate isOptionalMemOffset() const {
969 if (!isImm())
971 return (this->*Pred)() ? DiagnosticPredicate::Match
972 : DiagnosticPredicate::NearMatch;
973 }
974
975 bool isSImm12Lsb00000() const {
976 return isSImmPred([](int64_t Imm) { return isShiftedInt<7, 5>(Imm); });
977 }
978
979 bool isSImm10Lsb0000NonZero() const {
980 return isSImmPred(
981 [](int64_t Imm) { return Imm != 0 && isShiftedInt<6, 4>(Imm); });
982 }
983
984 bool isSImm16NonZero() const {
985 return isSImmPred([](int64_t Imm) { return Imm != 0 && isInt<16>(Imm); });
986 }
987
988 bool isUImm16NonZero() const {
989 return isUImmPred([](int64_t Imm) { return isUInt<16>(Imm) && Imm != 0; });
990 }
991
992 bool isSImm20LI() const {
993 if (!isExpr())
994 return false;
995
996 int64_t Imm;
997 if (evaluateConstantExpr(getExpr(), Imm))
998 return isInt<20>(fixImmediateForRV32(Imm, isRV64Expr()));
999
1001 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
1002 VK == RISCV::S_QC_ABS20;
1003 }
1004
1005 bool isSImm8PLI_B() const { return isSImm<8>() || isUImm<8>(); }
1006 bool isSImm10PLUI() const { return isSImm<10>() || isUImm<10>(); }
1007
1008 bool isSImm10PLI_H() const {
1009 return isSImm<10>() || isUImmPred([](int64_t Imm) {
1010 return isUInt<16>(Imm) && isInt<10>(SignExtend64<16>(Imm));
1011 });
1012 }
1013 bool isSImm10PLI_W() const {
1014 return isSImm<10>() || isUImmPred([](int64_t Imm) {
1015 return isUInt<32>(Imm) && isInt<10>(SignExtend64<32>(Imm));
1016 });
1017 }
1018
1019 bool isUImm20LUI() const {
1020 if (!isExpr())
1021 return false;
1022
1023 int64_t Imm;
1024 if (evaluateConstantExpr(getExpr(), Imm))
1025 return isUInt<20>(Imm);
1026
1028 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
1029 (VK == ELF::R_RISCV_HI20 || VK == ELF::R_RISCV_TPREL_HI20);
1030 }
1031
1032 bool isUImm20AUIPC() const {
1033 if (!isExpr())
1034 return false;
1035
1036 int64_t Imm;
1037 if (evaluateConstantExpr(getExpr(), Imm))
1038 return isUInt<20>(Imm);
1039
1041 return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
1042 (VK == RISCV::S_PCREL_HI || VK == RISCV::S_GOT_HI ||
1043 VK == ELF::R_RISCV_TLS_GOT_HI20 || VK == ELF::R_RISCV_TLS_GD_HI20 ||
1044 VK == ELF::R_RISCV_TLSDESC_HI20);
1045 }
1046
1047 bool isImmZero() const {
1048 return isUImmPred([](int64_t Imm) { return 0 == Imm; });
1049 }
1050
1051 bool isImmThree() const {
1052 return isUImmPred([](int64_t Imm) { return 3 == Imm; });
1053 }
1054
1055 bool isImmFour() const {
1056 return isUImmPred([](int64_t Imm) { return 4 == Imm; });
1057 }
1058
1059 bool isImm5Zibi() const {
1060 return isUImmPred(
1061 [](int64_t Imm) { return (Imm != 0 && isUInt<5>(Imm)) || Imm == -1; });
1062 }
1063
1064 bool isSImm5Plus1() const {
1065 return isSImmPred(
1066 [](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(Imm - 1); });
1067 }
1068
1069 bool isSImm18() const {
1070 return isSImmPred([](int64_t Imm) { return isInt<18>(Imm); });
1071 }
1072
1073 bool isSImm18Lsb0() const {
1074 return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 1>(Imm); });
1075 }
1076
1077 bool isSImm19Lsb00() const {
1078 return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 2>(Imm); });
1079 }
1080
1081 bool isSImm20Lsb000() const {
1082 return isSImmPred([](int64_t Imm) { return isShiftedInt<17, 3>(Imm); });
1083 }
1084
1085 bool isSImm32Lsb0() const {
1086 return isSImmPred([](int64_t Imm) { return isShiftedInt<31, 1>(Imm); });
1087 }
1088
1089 /// getStartLoc - Gets location of the first token of this operand
1090 SMLoc getStartLoc() const override { return StartLoc; }
1091 /// getEndLoc - Gets location of the last token of this operand
1092 SMLoc getEndLoc() const override { return EndLoc; }
1093
1094 /// True if this operand is for an RV64 instruction
1095 bool isRV64Expr() const {
1096 assert(Kind == KindTy::Expression && "Invalid type access!");
1097 return Expr.IsRV64;
1098 }
1099
1100 MCRegister getReg() const override {
1101 assert(Kind == KindTy::Register && "Invalid type access!");
1102 return Reg.Reg;
1103 }
1104
1105 StringRef getSysReg() const {
1106 assert(Kind == KindTy::SystemRegister && "Invalid type access!");
1107 return StringRef(SysReg.Data, SysReg.Length);
1108 }
1109
1110 const MCExpr *getExpr() const {
1111 assert(Kind == KindTy::Expression && "Invalid type access!");
1112 return Expr.Expr;
1113 }
1114
1115 uint64_t getFPConst() const {
1116 assert(Kind == KindTy::FPImmediate && "Invalid type access!");
1117 return FPImm.Val;
1118 }
1119
1120 StringRef getToken() const {
1121 assert(Kind == KindTy::Token && "Invalid type access!");
1122 return Tok;
1123 }
1124
1125 unsigned getVType() const {
1126 assert(Kind == KindTy::VType && "Invalid type access!");
1127 return VType.Val;
1128 }
1129
1130 RISCVFPRndMode::RoundingMode getFRM() const {
1131 assert(Kind == KindTy::FRM && "Invalid type access!");
1132 return FRM.FRM;
1133 }
1134
1135 unsigned getFence() const {
1136 assert(Kind == KindTy::Fence && "Invalid type access!");
1137 return Fence.Val;
1138 }
1139
1140 XSMTVTypeMode::SMTVTypeMode getSMTVType() const {
1141 assert(Kind == KindTy::SMTVType && "Invalid type access!");
1142 return SMTVType.SMTVType;
1143 }
1144
1145 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
1146 auto RegName = [](MCRegister Reg) {
1147 if (Reg)
1149 else
1150 return "noreg";
1151 };
1152
1153 switch (Kind) {
1154 case KindTy::Expression:
1155 OS << "<imm: ";
1156 MAI.printExpr(OS, *Expr.Expr);
1157 OS << ' ' << (Expr.IsRV64 ? "rv64" : "rv32") << '>';
1158 break;
1159 case KindTy::FPImmediate:
1160 OS << "<fpimm: " << FPImm.Val << ">";
1161 break;
1162 case KindTy::Register:
1163 OS << "<reg: " << RegName(Reg.Reg) << " (" << Reg.Reg.id()
1164 << (Reg.IsGPRAsFPR ? ") GPRasFPR>" : ")>");
1165 break;
1166 case KindTy::Token:
1167 OS << "'" << getToken() << "'";
1168 break;
1169 case KindTy::SystemRegister:
1170 OS << "<sysreg: " << getSysReg() << " (" << SysReg.Encoding << ")>";
1171 break;
1172 case KindTy::VType:
1173 OS << "<vtype: ";
1174 RISCVVType::printVType(getVType(), OS);
1175 OS << '>';
1176 break;
1177 case KindTy::FRM:
1178 OS << "<frm: ";
1179 OS << roundingModeToString(getFRM());
1180 OS << '>';
1181 break;
1182 case KindTy::SMTVType:
1183 OS << "<smtvtype: ";
1184 OS << SMTVTypeModeToString(getSMTVType());
1185 OS << '>';
1186 break;
1187 case KindTy::Fence:
1188 OS << "<fence: ";
1189 OS << getFence();
1190 OS << '>';
1191 break;
1192 case KindTy::RegList:
1193 OS << "<reglist: ";
1194 RISCVZC::printRegList(RegList.Encoding, OS);
1195 OS << '>';
1196 break;
1197 case KindTy::StackAdj:
1198 OS << "<stackadj: ";
1199 OS << StackAdj.Val;
1200 OS << '>';
1201 break;
1202 case KindTy::RegReg:
1203 OS << "<RegReg: BaseReg " << RegName(RegReg.BaseReg) << " OffsetReg "
1204 << RegName(RegReg.OffsetReg);
1205 break;
1206 }
1207 }
1208
1209 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
1210 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1211 Op->Tok = Str;
1212 Op->StartLoc = S;
1213 Op->EndLoc = S;
1214 return Op;
1215 }
1216
1217 static std::unique_ptr<RISCVOperand>
1218 createReg(MCRegister Reg, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
1219 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1220 Op->Reg.Reg = Reg;
1221 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1222 Op->StartLoc = S;
1223 Op->EndLoc = E;
1224 return Op;
1225 }
1226
1227 static std::unique_ptr<RISCVOperand> createExpr(const MCExpr *Val, SMLoc S,
1228 SMLoc E, bool IsRV64) {
1229 auto Op = std::make_unique<RISCVOperand>(KindTy::Expression);
1230 Op->Expr.Expr = Val;
1231 Op->Expr.IsRV64 = IsRV64;
1232 Op->StartLoc = S;
1233 Op->EndLoc = E;
1234 return Op;
1235 }
1236
1237 static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
1238 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1239 Op->FPImm.Val = Val;
1240 Op->StartLoc = S;
1241 Op->EndLoc = S;
1242 return Op;
1243 }
1244
1245 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
1246 unsigned Encoding) {
1247 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1248 Op->SysReg.Data = Str.data();
1249 Op->SysReg.Length = Str.size();
1250 Op->SysReg.Encoding = Encoding;
1251 Op->StartLoc = S;
1252 Op->EndLoc = S;
1253 return Op;
1254 }
1255
1256 static std::unique_ptr<RISCVOperand>
1257 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
1258 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1259 Op->FRM.FRM = FRM;
1260 Op->StartLoc = S;
1261 Op->EndLoc = S;
1262 return Op;
1263 }
1264
1265 static std::unique_ptr<RISCVOperand>
1266 createSMTVType(XSMTVTypeMode::SMTVTypeMode VType, SMLoc S) {
1267 auto Op = std::make_unique<RISCVOperand>(KindTy::SMTVType);
1268 Op->SMTVType.SMTVType = VType;
1269 Op->StartLoc = S;
1270 Op->EndLoc = S;
1271 return Op;
1272 }
1273
1274 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
1275 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1276 Op->Fence.Val = Val;
1277 Op->StartLoc = S;
1278 Op->EndLoc = S;
1279 return Op;
1280 }
1281
1282 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
1283 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1284 Op->VType.Val = VTypeI;
1285 Op->StartLoc = S;
1286 Op->EndLoc = S;
1287 return Op;
1288 }
1289
1290 static std::unique_ptr<RISCVOperand> createRegList(unsigned RlistEncode,
1291 SMLoc S) {
1292 auto Op = std::make_unique<RISCVOperand>(KindTy::RegList);
1293 Op->RegList.Encoding = RlistEncode;
1294 Op->StartLoc = S;
1295 return Op;
1296 }
1297
1298 static std::unique_ptr<RISCVOperand>
1299 createRegReg(MCRegister BaseReg, MCRegister OffsetReg, SMLoc S) {
1300 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1301 Op->RegReg.BaseReg = BaseReg;
1302 Op->RegReg.OffsetReg = OffsetReg;
1303 Op->StartLoc = S;
1304 Op->EndLoc = S;
1305 return Op;
1306 }
1307
1308 static std::unique_ptr<RISCVOperand> createStackAdj(unsigned StackAdj, SMLoc S) {
1309 auto Op = std::make_unique<RISCVOperand>(KindTy::StackAdj);
1310 Op->StackAdj.Val = StackAdj;
1311 Op->StartLoc = S;
1312 return Op;
1313 }
1314
1315 static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
1316 assert(Expr && "Expr shouldn't be null!");
1317 int64_t Imm = 0;
1318 bool IsConstant = evaluateConstantExpr(Expr, Imm);
1319
1320 if (IsConstant)
1321 Inst.addOperand(
1322 MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
1323 else
1325 }
1326
1327 // Used by the TableGen Code
1328 void addRegOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
1331 }
1332
1333 void addImmOperands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
1335 addExpr(Inst, getExpr(), isRV64Expr());
1336 }
1337
1338 template <unsigned Bits>
1339 void addSExtImmOperands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
1341 int64_t Imm;
1342 [[maybe_unused]] bool IsConstant = evaluateConstantExpr(getExpr(), Imm);
1343 assert(IsConstant);
1345 }
1346
1347 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1348 assert(N == 1 && "Invalid number of operands!");
1349 if (isExpr()) {
1350 addExpr(Inst, getExpr(), isRV64Expr());
1351 return;
1352 }
1353
1355 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1357 }
1358
1359 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
1360 assert(N == 1 && "Invalid number of operands!");
1362 }
1363
1364 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
1366 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
1367 }
1368
1369 // Support non-canonical syntax:
1370 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1371 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1372 void addVTypeIOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 int64_t Imm = 0;
1375 if (Kind == KindTy::Expression) {
1376 [[maybe_unused]] bool IsConstantImm =
1377 evaluateConstantExpr(getExpr(), Imm);
1378 assert(IsConstantImm && "Invalid VTypeI Operand!");
1379 } else {
1380 Imm = getVType();
1381 }
1383 }
1384
1385 void addRegListOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 Inst.addOperand(MCOperand::createImm(RegList.Encoding));
1388 }
1389
1390 void addRegRegOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 2 && "Invalid number of operands!");
1392 Inst.addOperand(MCOperand::createReg(RegReg.BaseReg));
1393 Inst.addOperand(MCOperand::createReg(RegReg.OffsetReg));
1394 }
1395
1396 void addStackAdjOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 Inst.addOperand(MCOperand::createImm(StackAdj.Val));
1399 }
1400
1401 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 Inst.addOperand(MCOperand::createImm(getFRM()));
1404 }
1405
1406 void addSMTVTypeOperand(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
1408 Inst.addOperand(MCOperand::createImm(getSMTVType()));
1409 }
1410};
1411} // end anonymous namespace.
1412
1413#define GET_REGISTER_MATCHER
1414#define GET_SUBTARGET_FEATURE_NAME
1415#define GET_MATCHER_IMPLEMENTATION
1416#define GET_MNEMONIC_SPELL_CHECKER
1417#include "RISCVGenAsmMatcher.inc"
1418
1420 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1421 return Reg - RISCV::F0_D + RISCV::F0_H;
1422}
1423
1425 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1426 return Reg - RISCV::F0_D + RISCV::F0_F;
1427}
1428
1430 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1431 return Reg - RISCV::F0_D + RISCV::F0_Q;
1432}
1433
1435 assert(Reg >= RISCV::X0 && Reg <= RISCV::X31 && "Invalid register");
1436 return Reg - RISCV::X0 + RISCV::X0_Y;
1437}
1438
1440 unsigned Kind) {
1441 unsigned RegClassID;
1442 if (Kind == MCK_VRM2)
1443 RegClassID = RISCV::VRM2RegClassID;
1444 else if (Kind == MCK_VRM4)
1445 RegClassID = RISCV::VRM4RegClassID;
1446 else if (Kind == MCK_VRM8)
1447 RegClassID = RISCV::VRM8RegClassID;
1448 else
1449 return MCRegister();
1450 return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
1451 &getRISCVMCRegisterClass(RegClassID));
1452}
1453
1455 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1456 return Reg - RISCV::F0_D + RISCV::F0_Q2;
1457}
1458
1459unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1460 unsigned Kind) {
1461 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1462 if (!Op.isReg())
1463 return Match_InvalidOperand;
1464
1465 MCRegister Reg = Op.getReg();
1466 bool IsRegFPR64 =
1467 getRISCVMCRegisterClass(RISCV::FPR64RegClassID).contains(Reg);
1468 bool IsRegFPR64C =
1469 getRISCVMCRegisterClass(RISCV::FPR64CRegClassID).contains(Reg);
1470 bool IsRegVR = getRISCVMCRegisterClass(RISCV::VRRegClassID).contains(Reg);
1471
1472 if (Op.isGPR() && Kind == MCK_YGPR) {
1473 // GPR and capability GPR use the same register names, convert if required.
1474 Op.Reg.Reg = convertGPRToYGPR(Reg);
1475 return Match_Success;
1476 }
1477 if (IsRegFPR64 && Kind == MCK_FPR256) {
1478 Op.Reg.Reg = convertFPR64ToFPR256(Reg);
1479 return Match_Success;
1480 }
1481 if (IsRegFPR64 && Kind == MCK_FPR128) {
1482 Op.Reg.Reg = convertFPR64ToFPR128(Reg);
1483 return Match_Success;
1484 }
1485 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1486 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1487 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1488 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1489 Op.Reg.Reg = convertFPR64ToFPR32(Reg);
1490 return Match_Success;
1491 }
1492 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1493 // register from FPR64 to FPR16 if necessary.
1494 if (IsRegFPR64 && Kind == MCK_FPR16) {
1495 Op.Reg.Reg = convertFPR64ToFPR16(Reg);
1496 return Match_Success;
1497 }
1498 if (Kind == MCK_GPRAsFPR16 && Op.isGPRAsFPR()) {
1499 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_H;
1500 return Match_Success;
1501 }
1502 if (Kind == MCK_GPRAsFPR32 && Op.isGPRAsFPR()) {
1503 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_W;
1504 return Match_Success;
1505 }
1506
1507 // There are some GPRF64AsFPR instructions that have no RV32 equivalent. We
1508 // reject them at parsing thinking we should match as GPRPairAsFPR for RV32.
1509 // So we explicitly accept them here for RV32 to allow the generic code to
1510 // report that the instruction requires RV64.
1511 if (getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg) &&
1512 Kind == MCK_GPRF64AsFPR && STI->hasFeature(RISCV::FeatureStdExtZdinx) &&
1513 !isRV64())
1514 return Match_Success;
1515
1516 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1517 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1518 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1519 Op.Reg.Reg = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1520 if (!Op.Reg.Reg)
1521 return Match_InvalidOperand;
1522 return Match_Success;
1523 }
1524 return Match_InvalidOperand;
1525}
1526
1527bool RISCVAsmParser::generateImmOutOfRangeError(
1528 SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
1529 const Twine &Msg = "immediate must be an integer in the range") {
1530 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1531}
1532
1533// Some diagnostics need to vary with subtarget features, so they are handled
1534// here. For example, several immediate ranges depend on whether the target is
1535// RV32 or RV64.
1536std::string RISCVAsmParser::getCustomOperandDiag(unsigned MatchError) {
1537 auto Range = [](int64_t Lower, int64_t Upper,
1538 StringRef Msg = "immediate must be an integer in the range") {
1539 return (Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]").str();
1540 };
1541
1542 switch (MatchError) {
1543 default:
1544 // For all other operand diagnostics, use the static string generated by
1545 // TableGen from the DiagnosticString field, if any.
1546 if (const char *Diag = getMatchKindDiag((RISCVMatchResultTy)MatchError))
1547 return Diag;
1548 return std::string();
1549 case Match_InvalidImmXLenLI:
1550 if (isRV64())
1551 return "operand must be a constant 64-bit integer";
1552 return Range(std::numeric_limits<int32_t>::min(),
1553 std::numeric_limits<uint32_t>::max());
1554 case Match_InvalidImmXLenLI_Restricted:
1555 if (isRV64())
1556 return "operand either must be a constant 64-bit integer "
1557 "or a bare symbol name";
1558 return Range(std::numeric_limits<int32_t>::min(),
1559 std::numeric_limits<uint32_t>::max(),
1560 "operand either must be a bare symbol name or an immediate "
1561 "integer in the range");
1562 case Match_InvalidUImmLog2XLen:
1563 if (isRV64())
1564 return Range(0, (1 << 6) - 1);
1565 return Range(0, (1 << 5) - 1);
1566 case Match_InvalidUImmLog2XLenNonZero:
1567 if (isRV64())
1568 return Range(1, (1 << 6) - 1);
1569 return Range(1, (1 << 5) - 1);
1570 case Match_InvalidUImm1:
1571 return Range(0, (1 << 1) - 1);
1572 case Match_InvalidUImm2:
1573 return Range(0, (1 << 2) - 1);
1574 case Match_InvalidUImm2Lsb0:
1575 return Range(0, 2, "immediate must be one of");
1576 case Match_InvalidUImm3:
1577 return Range(0, (1 << 3) - 1);
1578 case Match_InvalidUImm4:
1579 return Range(0, (1 << 4) - 1);
1580 case Match_InvalidUImm4Plus1:
1581 return Range(1, (1 << 4));
1582 case Match_InvalidUImm5:
1583 return Range(0, (1 << 5) - 1);
1584 case Match_InvalidUImm5NonZero:
1585 return Range(1, (1 << 5) - 1);
1586 case Match_InvalidUImm5GT3:
1587 return Range(4, (1 << 5) - 1);
1588 case Match_InvalidUImm5Plus1:
1589 return Range(1, (1 << 5));
1590 case Match_InvalidUImm5GE6Plus1:
1591 return Range(6, (1 << 5));
1592 case Match_InvalidUImm5Slist:
1593 return "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31";
1594 case Match_InvalidUImm6:
1595 return Range(0, (1 << 6) - 1);
1596 case Match_InvalidUImm6Plus1:
1597 return Range(1, (1 << 6));
1598 case Match_InvalidUImm7:
1599 return Range(0, (1 << 7) - 1);
1600 case Match_InvalidUImm8:
1601 return Range(0, (1 << 8) - 1);
1602 case Match_InvalidUImm8GE32:
1603 return Range(32, (1 << 8) - 1);
1604 case Match_InvalidSImm5:
1605 return Range(-(1 << 4), (1 << 4) - 1);
1606 case Match_InvalidSImm5NonZero:
1607 return Range(-(1 << 4), (1 << 4) - 1,
1608 "immediate must be non-zero in the range");
1609 case Match_InvalidSImm6:
1610 return Range(-(1 << 5), (1 << 5) - 1);
1611 case Match_InvalidSImm6NonZero:
1612 return Range(-(1 << 5), (1 << 5) - 1,
1613 "immediate must be non-zero in the range");
1614 case Match_InvalidCLUIImm:
1615 return Range(1, (1 << 5) - 1, "immediate must be in [0xfffe0, 0xfffff] or");
1616 case Match_InvalidUImm5Lsb0:
1617 return Range(0, (1 << 5) - 2,
1618 "immediate must be a multiple of 2 bytes in the range");
1619 case Match_InvalidUImm6Lsb0:
1620 return Range(0, (1 << 6) - 2,
1621 "immediate must be a multiple of 2 bytes in the range");
1622 case Match_InvalidUImm6Lsb000:
1623 return Range(0, (1 << 6) - 8,
1624 "immediate must be a multiple of 8 in the range");
1625 case Match_InvalidUImm7Lsb00:
1626 return Range(0, (1 << 7) - 4,
1627 "immediate must be a multiple of 4 bytes in the range");
1628 case Match_InvalidUImm8Lsb00:
1629 return Range(0, (1 << 8) - 4,
1630 "immediate must be a multiple of 4 bytes in the range");
1631 case Match_InvalidUImm8Lsb000:
1632 return Range(0, (1 << 8) - 8,
1633 "immediate must be a multiple of 8 bytes in the range");
1634 case Match_InvalidUImm9:
1635 return Range(0, (1 << 9) - 1, "immediate offset must be in the range");
1636 case Match_InvalidBareSImm9Lsb0:
1637 return Range(-(1 << 8), (1 << 8) - 2,
1638 "immediate must be a multiple of 2 bytes in the range");
1639 case Match_InvalidUImm9Lsb000:
1640 return Range(0, (1 << 9) - 8,
1641 "immediate must be a multiple of 8 bytes in the range");
1642 case Match_InvalidSImm8PLI_B:
1643 return Range(-(1 << 7), (1 << 8) - 1);
1644 case Match_InvalidSImm10:
1645 case Match_InvalidSImm10PLI_H:
1646 case Match_InvalidSImm10PLI_W:
1647 return Range(-(1 << 9), (1 << 9) - 1);
1648 case Match_InvalidSImm10PLUI:
1649 return Range(-(1 << 9), (1 << 10) - 1);
1650 case Match_InvalidUImm10Lsb00NonZero:
1651 return Range(4, (1 << 10) - 4,
1652 "immediate must be a multiple of 4 bytes in the range");
1653 case Match_InvalidSImm10Lsb0000NonZero:
1654 return Range(
1655 -(1 << 9), (1 << 9) - 16,
1656 "immediate must be a multiple of 16 bytes and non-zero in the range");
1657 case Match_InvalidSImm11:
1658 return Range(-(1 << 10), (1 << 10) - 1);
1659 case Match_InvalidBareSImm11Lsb0:
1660 return Range(-(1 << 10), (1 << 10) - 2,
1661 "immediate must be a multiple of 2 bytes in the range");
1662 case Match_InvalidUImm10:
1663 return Range(0, (1 << 10) - 1);
1664 case Match_InvalidUImm11:
1665 return Range(0, (1 << 11) - 1);
1666 case Match_InvalidUImm14Lsb00:
1667 return Range(0, (1 << 14) - 4,
1668 "immediate must be a multiple of 4 bytes in the range");
1669 case Match_InvalidUImm16NonZero:
1670 return Range(1, (1 << 16) - 1);
1671 case Match_InvalidSImm12:
1672 return Range(-(1 << 11), (1 << 11) - 1);
1673 case Match_InvalidSImm12LO:
1674 return Range(-(1 << 11), (1 << 11) - 1,
1675 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo "
1676 "specifier or an integer in the range");
1677 case Match_InvalidBareSImm12Lsb0:
1678 return Range(-(1 << 11), (1 << 11) - 2,
1679 "immediate must be a multiple of 2 bytes in the range");
1680 case Match_InvalidSImm12Lsb00000:
1681 return Range(-(1 << 11), (1 << 11) - 32,
1682 "immediate must be a multiple of 32 bytes in the range");
1683 case Match_InvalidBareSImm13Lsb0:
1684 return Range(-(1 << 12), (1 << 12) - 2,
1685 "immediate must be a multiple of 2 bytes in the range");
1686 case Match_InvalidSImm16:
1687 return Range(-(1 << 15), (1 << 15) - 1);
1688 case Match_InvalidSImm16NonZero:
1689 return Range(-(1 << 15), (1 << 15) - 1,
1690 "immediate must be non-zero in the range");
1691 case Match_InvalidSImm20LI:
1692 return Range(-(1 << 19), (1 << 19) - 1,
1693 "operand must be a symbol with a %qc.abs20 specifier or an "
1694 "integer in the range");
1695 case Match_InvalidUImm20LUI:
1696 return Range(0, (1 << 20) - 1,
1697 "operand must be a symbol with %hi/%tprel_hi specifier or an "
1698 "integer in the range");
1699 case Match_InvalidUImm20:
1700 return Range(0, (1 << 20) - 1);
1701 case Match_InvalidUImm20AUIPC:
1702 return Range(
1703 0, (1 << 20) - 1,
1704 "operand must be a symbol with a "
1705 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi specifier "
1706 "or an integer in the range");
1707 case Match_InvalidBareSImm21Lsb0:
1708 return Range(-(1 << 20), (1 << 20) - 2,
1709 "immediate must be a multiple of 2 bytes in the range");
1710 case Match_InvalidCSRSystemRegister:
1711 return Range(0, (1 << 12) - 1,
1712 "operand must be a valid system register name or an integer "
1713 "in the range");
1714 case Match_InvalidImm5Zibi:
1715 return Range(-1, (1 << 5) - 1, "immediate must be non-zero in the range");
1716 case Match_InvalidVTypeI:
1717 return "operand must be "
1718 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]";
1719 case Match_InvalidSImm5Plus1:
1720 return Range(-(1 << 4) + 1, (1 << 4), "immediate must be in the range");
1721 case Match_InvalidSImm18:
1722 return Range(-(1 << 17), (1 << 17) - 1);
1723 case Match_InvalidSImm18Lsb0:
1724 return Range(-(1 << 17), (1 << 17) - 2,
1725 "immediate must be a multiple of 2 bytes in the range");
1726 case Match_InvalidSImm19Lsb00:
1727 return Range(-(1 << 18), (1 << 18) - 4,
1728 "immediate must be a multiple of 4 bytes in the range");
1729 case Match_InvalidSImm20Lsb000:
1730 return Range(-(1 << 19), (1 << 19) - 8,
1731 "immediate must be a multiple of 8 bytes in the range");
1732 case Match_InvalidSImm26:
1733 return Range(-(1 << 25), (1 << 25) - 1);
1734 // HACK: See comment before `BareSymbolQC_E_LI` in RISCVInstrInfoXqci.td.
1735 case Match_InvalidBareSymbolQC_E_LI:
1736 [[fallthrough]];
1737 // END HACK
1738 case Match_InvalidBareSImm32:
1739 return Range(std::numeric_limits<int32_t>::min(),
1740 std::numeric_limits<uint32_t>::max());
1741 case Match_InvalidBareSImm32Lsb0:
1742 return Range(std::numeric_limits<int32_t>::min(),
1743 std::numeric_limits<int32_t>::max() - 1,
1744 "operand must be a multiple of 2 bytes in the range");
1745 case Match_InvalidRnumArg:
1746 return Range(0, 10);
1747 case Match_InvalidStackAdj:
1748 return "stack adjustment is invalid for this instruction and register "
1749 "list";
1750 case Match_InvalidYBNDSWImm:
1751 return "immediate must be an integer in the range "
1752 "[1, 255], a multiple of 8 in the range [256, 504], "
1753 "or a multiple of 16 in the range [512, 4096]";
1754 case Match_InvalidUImm7EqXLen:
1755 return ("immediate must be an integer equal to XLEN (" +
1756 Twine(isRV64() ? "64" : "32") + ")")
1757 .str();
1758 }
1759}
1760
1761// Process the list of near-misses, throwing away ones we don't want to report
1762// to the user, and converting the rest to a source location and string that
1763// should be reported.
1764void RISCVAsmParser::FilterNearMisses(
1765 SmallVectorImpl<NearMissInfo> &NearMissesIn,
1766 SmallVectorImpl<NearMissMessage> &NearMissesOut, SMLoc IDLoc,
1768 // Record some information about near-misses that we have already seen, so
1769 // that we can avoid reporting redundant ones.
1770 std::multimap<unsigned, unsigned> OperandMissesSeen;
1771 SmallSet<FeatureBitset, 4> FeatureMissesSeen;
1772 bool ReportedTooFewOperands = false;
1773 bool ReportedTooManyOperands = false;
1774
1775 for (NearMissInfo &I : NearMissesIn) {
1776 switch (I.getKind()) {
1778 SMLoc OperandLoc =
1779 ((RISCVOperand &)*Operands[I.getOperandIndex()]).getStartLoc();
1780
1781 // When the matcher finds surplus operands, it records them as
1782 // NearMissOperand with InvalidMatchClass. We detect this and report
1783 // "unexpected extra operand" instead of "invalid operand".
1784 if (I.getOperandClass() == InvalidMatchClass) {
1785 if (!ReportedTooManyOperands) {
1786 NearMissesOut.emplace_back(NearMissMessage{
1787 OperandLoc, "unexpected extra operand for instruction"});
1788 ReportedTooManyOperands = true;
1789 }
1790 break;
1791 }
1792
1793 std::string OperandDiag = getCustomOperandDiag(I.getOperandError());
1794
1795 // If we have already emitted a message for a superclass on this operand,
1796 // don't also report the sub-class.
1797 unsigned DupCheckMatchClass =
1798 OperandDiag.empty() ? ~0U : I.getOperandClass();
1799 auto PrevReports = OperandMissesSeen.equal_range(I.getOperandIndex());
1800 if (std::any_of(
1801 PrevReports.first, PrevReports.second,
1802 [DupCheckMatchClass](const std::pair<unsigned, unsigned> Pair) {
1803 if (DupCheckMatchClass == ~0U || Pair.second == ~0U)
1804 return Pair.second == DupCheckMatchClass;
1805 return isSubclass((MatchClassKind)DupCheckMatchClass,
1806 (MatchClassKind)Pair.second);
1807 }))
1808 break;
1809 OperandMissesSeen.insert(
1810 std::make_pair(I.getOperandIndex(), DupCheckMatchClass));
1811
1812 NearMissMessage Message;
1813 Message.Loc = OperandLoc;
1814 if (!OperandDiag.empty()) {
1815 Message.Message = OperandDiag;
1816 } else {
1817 Message.Message = "invalid operand for instruction";
1818 LLVM_DEBUG(
1819 dbgs() << "Missing diagnostic string for operand class "
1820 << getMatchClassName((MatchClassKind)I.getOperandClass())
1821 << I.getOperandClass() << ", error " << I.getOperandError()
1822 << ", opcode " << MII.getName(I.getOpcode()) << "\n");
1823 }
1824 NearMissesOut.emplace_back(Message);
1825 break;
1826 }
1828 const FeatureBitset &MissingFeatures = I.getFeatures();
1829 // Don't report the same set of features twice.
1830 if (!FeatureMissesSeen.insert(MissingFeatures).second)
1831 break;
1832
1833 NearMissMessage Message;
1834 Message.Loc = IDLoc;
1835 bool FirstFeature = true;
1836 Message.Message = "instruction requires the following:";
1837 for (unsigned Feature : MissingFeatures) {
1838 Message.Message += FirstFeature ? " " : ", ";
1839 Message.Message += getSubtargetFeatureName(Feature);
1840 FirstFeature = false;
1841 }
1842 NearMissesOut.emplace_back(Message);
1843 break;
1844 }
1846 // RISC-V does not define any target match predicates.
1847 llvm_unreachable("RISC-V has no target predicate near-misses");
1848 break;
1850 if (!ReportedTooFewOperands) {
1851 SMLoc EndLoc = ((RISCVOperand &)*Operands.back()).getEndLoc();
1852 NearMissesOut.emplace_back(
1853 NearMissMessage{EndLoc, "too few operands for instruction"});
1854 ReportedTooFewOperands = true;
1855 }
1856 break;
1857 }
1859 // This should never leave the matcher.
1860 llvm_unreachable("not a near-miss");
1861 break;
1862 }
1863 }
1864}
1865
1866void RISCVAsmParser::ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses,
1867 SMLoc IDLoc, OperandVector &Operands) {
1869 FilterNearMisses(NearMisses, Messages, IDLoc, Operands);
1870
1871 if (Messages.empty()) {
1872 // No near-misses were found, so the best we can do is "invalid
1873 // instruction".
1874 Error(IDLoc, "invalid instruction");
1875 } else if (Messages.size() == 1) {
1876 // One near miss was found, report it as the sole error.
1877 Error(Messages[0].Loc, Messages[0].Message);
1878 } else {
1879 // More than one near miss, so report a generic "invalid instruction"
1880 // error, followed by notes for each of the near-misses.
1881 Error(IDLoc,
1882 "invalid instruction, any one of the following would fix this:");
1883 for (auto &M : Messages)
1884 Note(M.Loc, M.Message);
1885 }
1886}
1887
1888bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1890 MCStreamer &Out,
1891 uint64_t &ErrorInfo,
1892 bool MatchingInlineAsm) {
1893 MCInst Inst;
1895
1896 auto Result =
1897 MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm);
1898 switch (Result) {
1899 default:
1900 break;
1901 case Match_Success:
1902 if (validateInstruction(Inst, Operands))
1903 return true;
1904 return processInstruction(Inst, IDLoc, Operands, Out);
1905 case Match_MnemonicFail: {
1906 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1907 std::string Suggestion = RISCVMnemonicSpellCheck(
1908 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1909 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1910 }
1911 case Match_NearMisses:
1912 ReportNearMisses(NearMisses, IDLoc, Operands);
1913 return true;
1914 }
1915
1916 llvm_unreachable("Unknown match type detected!");
1917}
1918
1919// Attempts to match Name as a register (either using the default name or
1920// alternative ABI names), returning the matching register. Upon failure,
1921// returns a non-valid MCRegister. If IsRVE, then registers x16-x31 will be
1922// rejected.
1923MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
1924 MCRegister Reg = MatchRegisterName(Name);
1925 // The 16-/32-/128- and 64-bit FPRs have the same asm name. Check
1926 // that the initial match always matches the 64-bit variant, and
1927 // not the 16/32/128-bit one.
1928 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1929 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1930 assert(!(Reg >= RISCV::F0_Q && Reg <= RISCV::F31_Q));
1931 // The default FPR register class is based on the tablegen enum ordering.
1932 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1933 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1934 static_assert(RISCV::F0_D < RISCV::F0_Q, "FPR matching must be updated");
1935 if (!Reg)
1936 Reg = MatchRegisterAltName(Name);
1937 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1938 Reg = MCRegister();
1939 return Reg;
1940}
1941
1942bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1943 SMLoc &EndLoc) {
1944 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1945 return Error(StartLoc, "invalid register name");
1946 return false;
1947}
1948
1949ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1950 SMLoc &EndLoc) {
1951 const AsmToken &Tok = getParser().getTok();
1952 StartLoc = Tok.getLoc();
1953 EndLoc = Tok.getEndLoc();
1954 StringRef Name = getLexer().getTok().getIdentifier();
1955
1957 if (!Reg)
1958 return ParseStatus::NoMatch;
1959
1960 getParser().Lex(); // Eat identifier token.
1961 return ParseStatus::Success;
1962}
1963
1964ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1965 bool AllowParens) {
1966 SMLoc FirstS = getLoc();
1967 bool HadParens = false;
1968 AsmToken LParen;
1969
1970 // If this is an LParen and a parenthesised register name is allowed, parse it
1971 // atomically.
1972 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1973 AsmToken Buf[2];
1974 size_t ReadCount = getLexer().peekTokens(Buf);
1975 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1976 HadParens = true;
1977 LParen = getParser().getTok();
1978 getParser().Lex(); // Eat '('
1979 }
1980 }
1981
1982 switch (getLexer().getKind()) {
1983 default:
1984 if (HadParens)
1985 getLexer().UnLex(LParen);
1986 return ParseStatus::NoMatch;
1988 StringRef Name = getLexer().getTok().getIdentifier();
1989 MCRegister Reg = matchRegisterNameHelper(Name);
1990
1991 if (!Reg) {
1992 if (HadParens)
1993 getLexer().UnLex(LParen);
1994 return ParseStatus::NoMatch;
1995 }
1996 if (HadParens)
1997 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1998 SMLoc S = getLoc();
1999 SMLoc E = getTok().getEndLoc();
2000 getLexer().Lex();
2001 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2002 }
2003
2004 if (HadParens) {
2005 getParser().Lex(); // Eat ')'
2006 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2007 }
2008
2009 return ParseStatus::Success;
2010}
2011
2012ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
2013 SMLoc S = getLoc();
2014 SMLoc E;
2015 const MCExpr *Res;
2016
2017 switch (getLexer().getKind()) {
2018 default:
2019 return ParseStatus::NoMatch;
2020 case AsmToken::LParen:
2021 case AsmToken::Minus:
2022 case AsmToken::Plus:
2023 case AsmToken::Exclaim:
2024 case AsmToken::Tilde:
2025 case AsmToken::Integer:
2026 case AsmToken::String: {
2027 if (getParser().parseExpression(Res, E))
2028 return ParseStatus::Failure;
2029
2030 auto *CE = dyn_cast<MCConstantExpr>(Res);
2031 if (CE) {
2032 int64_t Imm = CE->getValue();
2033 if (isUInt<7>(Imm)) {
2034 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2035 return ParseStatus::Success;
2036 }
2037 }
2038
2039 break;
2040 }
2041 case AsmToken::Identifier: {
2042 StringRef Identifier;
2043 if (getParser().parseIdentifier(Identifier))
2044 return ParseStatus::Failure;
2045
2046 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
2047 if (Opcode) {
2048 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
2049 "Unexpected opcode");
2050 Res = MCConstantExpr::create(Opcode->Value, getContext());
2052 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2053 return ParseStatus::Success;
2054 }
2055
2056 break;
2057 }
2058 case AsmToken::Percent:
2059 break;
2060 }
2061
2062 return generateImmOutOfRangeError(
2063 S, 0, 127,
2064 "opcode must be a valid opcode name or an immediate in the range");
2065}
2066
2067ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
2068 SMLoc S = getLoc();
2069 SMLoc E;
2070 const MCExpr *Res;
2071
2072 switch (getLexer().getKind()) {
2073 default:
2074 return ParseStatus::NoMatch;
2075 case AsmToken::LParen:
2076 case AsmToken::Minus:
2077 case AsmToken::Plus:
2078 case AsmToken::Exclaim:
2079 case AsmToken::Tilde:
2080 case AsmToken::Integer:
2081 case AsmToken::String: {
2082 if (getParser().parseExpression(Res, E))
2083 return ParseStatus::Failure;
2084
2085 auto *CE = dyn_cast<MCConstantExpr>(Res);
2086 if (CE) {
2087 int64_t Imm = CE->getValue();
2088 if (Imm >= 0 && Imm <= 2) {
2089 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2090 return ParseStatus::Success;
2091 }
2092 }
2093
2094 break;
2095 }
2096 case AsmToken::Identifier: {
2097 StringRef Identifier;
2098 if (getParser().parseIdentifier(Identifier))
2099 return ParseStatus::Failure;
2100
2101 unsigned Opcode;
2102 if (Identifier == "C0")
2103 Opcode = 0;
2104 else if (Identifier == "C1")
2105 Opcode = 1;
2106 else if (Identifier == "C2")
2107 Opcode = 2;
2108 else
2109 break;
2110
2111 Res = MCConstantExpr::create(Opcode, getContext());
2113 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2114 return ParseStatus::Success;
2115 }
2116 case AsmToken::Percent: {
2117 // Discard operand with modifier.
2118 break;
2119 }
2120 }
2121
2122 return generateImmOutOfRangeError(
2123 S, 0, 2,
2124 "opcode must be a valid opcode name or an immediate in the range");
2125}
2126
2127ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
2128 SMLoc S = getLoc();
2129 const MCExpr *Res;
2130
2131 auto SysRegFromConstantInt = [this](const MCExpr *E, SMLoc S) {
2132 if (auto *CE = dyn_cast<MCConstantExpr>(E)) {
2133 int64_t Imm = CE->getValue();
2134 if (isUInt<12>(Imm)) {
2135 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
2136 // Accept an immediate representing a named Sys Reg if it satisfies the
2137 // the required features.
2138 for (auto &Reg : Range) {
2139 if (Reg.IsAltName || Reg.IsDeprecatedName)
2140 continue;
2141 if (Reg.haveRequiredFeatures(STI->getFeatureBits()))
2142 return RISCVOperand::createSysReg(
2143 RISCVSysReg::getSysRegStr(Reg.Name), S, Imm);
2144 }
2145 // Accept an immediate representing an un-named Sys Reg if the range is
2146 // valid, regardless of the required features.
2147 return RISCVOperand::createSysReg("", S, Imm);
2148 }
2149 }
2150 return std::unique_ptr<RISCVOperand>();
2151 };
2152
2153 switch (getLexer().getKind()) {
2154 default:
2155 return ParseStatus::NoMatch;
2156 case AsmToken::LParen:
2157 case AsmToken::Minus:
2158 case AsmToken::Plus:
2159 case AsmToken::Exclaim:
2160 case AsmToken::Tilde:
2161 case AsmToken::Integer:
2162 case AsmToken::String: {
2163 if (getParser().parseExpression(Res))
2164 return ParseStatus::Failure;
2165
2166 if (auto SysOpnd = SysRegFromConstantInt(Res, S)) {
2167 Operands.push_back(std::move(SysOpnd));
2168 return ParseStatus::Success;
2169 }
2170
2171 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2172 }
2173 case AsmToken::Identifier: {
2174 StringRef Identifier;
2175 if (getParser().parseIdentifier(Identifier))
2176 return ParseStatus::Failure;
2177
2178 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
2179
2180 if (SysReg) {
2181 if (SysReg->IsDeprecatedName) {
2182 // Lookup the undeprecated name.
2183 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);
2184 for (auto &Reg : Range) {
2185 if (Reg.IsAltName || Reg.IsDeprecatedName)
2186 continue;
2187 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
2188 RISCVSysReg::getSysRegStr(Reg.Name) + "'");
2189 }
2190 }
2191
2192 // Accept a named Sys Reg if the required features are present.
2193 const auto &FeatureBits = getSTI().getFeatureBits();
2194 const auto &AllFeatures = getSTI().getAllProcessorFeatures();
2195 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
2196 const auto *Feature =
2197 llvm::find_if(AllFeatures, [&](const auto &Feature) {
2198 return SysReg->FeaturesRequired[Feature.Value];
2199 });
2200 std::string ErrorMsg =
2201 std::string("system register '") +
2202 std::string(RISCVSysReg::getSysRegStr(SysReg->Name)) + "' ";
2203 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
2204 ErrorMsg += "is RV32 only";
2205 if (Feature != std::end(AllFeatures))
2206 ErrorMsg += " and ";
2207 }
2208 if (Feature != std::end(AllFeatures)) {
2209 ErrorMsg +=
2210 "requires '" + std::string(Feature->key()) + "' to be enabled";
2211 }
2212
2213 return Error(S, ErrorMsg);
2214 }
2215 Operands.push_back(
2216 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
2217 return ParseStatus::Success;
2218 }
2219
2220 // Accept a symbol name that evaluates to an absolute value.
2221 MCSymbol *Sym = getContext().lookupSymbol(Identifier);
2222 if (Sym && Sym->isVariable()) {
2223 // Pass false for SetUsed, since redefining the value later does not
2224 // affect this instruction.
2225 if (auto SysOpnd = SysRegFromConstantInt(Sym->getVariableValue(), S)) {
2226 Operands.push_back(std::move(SysOpnd));
2227 return ParseStatus::Success;
2228 }
2229 }
2230
2231 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2232 "operand must be a valid system register "
2233 "name or an integer in the range");
2234 }
2235 case AsmToken::Percent: {
2236 // Discard operand with modifier.
2237 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2238 }
2239 }
2240
2241 return ParseStatus::NoMatch;
2242}
2243
2244ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
2245 SMLoc S = getLoc();
2246
2247 // Parse special floats (inf/nan/min) representation.
2248 if (getTok().is(AsmToken::Identifier)) {
2249 StringRef Identifier = getTok().getIdentifier();
2250 if (Identifier.compare_insensitive("inf") == 0) {
2251 Operands.push_back(
2252 RISCVOperand::createExpr(MCConstantExpr::create(30, getContext()), S,
2253 getTok().getEndLoc(), isRV64()));
2254 } else if (Identifier.compare_insensitive("nan") == 0) {
2255 Operands.push_back(
2256 RISCVOperand::createExpr(MCConstantExpr::create(31, getContext()), S,
2257 getTok().getEndLoc(), isRV64()));
2258 } else if (Identifier.compare_insensitive("min") == 0) {
2259 Operands.push_back(
2260 RISCVOperand::createExpr(MCConstantExpr::create(1, getContext()), S,
2261 getTok().getEndLoc(), isRV64()));
2262 } else {
2263 return TokError("invalid floating point literal");
2264 }
2265
2266 Lex(); // Eat the token.
2267
2268 return ParseStatus::Success;
2269 }
2270
2271 // Handle negation, as that still comes through as a separate token.
2272 bool IsNegative = parseOptionalToken(AsmToken::Minus);
2273
2274 const AsmToken &Tok = getTok();
2275 if (!Tok.is(AsmToken::Real))
2276 return TokError("invalid floating point immediate");
2277
2278 // Parse FP representation.
2279 APFloat RealVal(APFloat::IEEEdouble());
2280 auto StatusOrErr =
2281 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2282 if (errorToBool(StatusOrErr.takeError()))
2283 return TokError("invalid floating point representation");
2284
2285 if (IsNegative)
2286 RealVal.changeSign();
2287
2288 Operands.push_back(RISCVOperand::createFPImm(
2289 RealVal.bitcastToAPInt().getZExtValue(), S));
2290
2291 Lex(); // Eat the token.
2292
2293 return ParseStatus::Success;
2294}
2295
2296ParseStatus RISCVAsmParser::parseExpression(OperandVector &Operands) {
2297 SMLoc S = getLoc();
2298 SMLoc E;
2299 const MCExpr *Res;
2300
2301 switch (getLexer().getKind()) {
2302 default:
2303 return ParseStatus::NoMatch;
2304 case AsmToken::LParen:
2305 case AsmToken::Dot:
2306 case AsmToken::Minus:
2307 case AsmToken::Plus:
2308 case AsmToken::Exclaim:
2309 case AsmToken::Tilde:
2310 case AsmToken::Integer:
2311 case AsmToken::String:
2313 if (getParser().parseExpression(Res, E))
2314 return ParseStatus::Failure;
2315 break;
2316 case AsmToken::Percent:
2317 return parseOperandWithSpecifier(Operands);
2318 }
2319
2320 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2321 return ParseStatus::Success;
2322}
2323
2324ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
2325 SMLoc S = getLoc();
2326 SMLoc E;
2327
2328 if (parseToken(AsmToken::Percent, "expected '%' relocation specifier"))
2329 return ParseStatus::Failure;
2330 const MCExpr *Expr = nullptr;
2331 bool Failed = parseExprWithSpecifier(Expr, E);
2332 if (!Failed)
2333 Operands.push_back(RISCVOperand::createExpr(Expr, S, E, isRV64()));
2334 return Failed;
2335}
2336
2337bool RISCVAsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
2338 SMLoc Loc = getLoc();
2339 if (getLexer().getKind() != AsmToken::Identifier)
2340 return TokError("expected '%' relocation specifier");
2341 StringRef Identifier = getParser().getTok().getIdentifier();
2342 auto Spec = RISCV::parseSpecifierName(Identifier);
2343 if (!Spec)
2344 return TokError("invalid relocation specifier");
2345
2346 getParser().Lex(); // Eat the identifier
2347 if (parseToken(AsmToken::LParen, "expected '('"))
2348 return true;
2349
2350 const MCExpr *SubExpr;
2351 if (getParser().parseParenExpression(SubExpr, E))
2352 return true;
2353
2354 Res = MCSpecifierExpr::create(SubExpr, Spec, getContext(), Loc);
2355 return false;
2356}
2357
2358bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {
2359 SMLoc E;
2360 if (parseOptionalToken(AsmToken::Percent))
2361 return parseExprWithSpecifier(Res, E);
2362 return getParser().parseExpression(Res);
2363}
2364
2365ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
2366 SMLoc S = getLoc();
2367 const MCExpr *Res;
2368
2369 if (getLexer().getKind() != AsmToken::Identifier)
2370 return ParseStatus::NoMatch;
2371
2372 StringRef Identifier = getTok().getIdentifier();
2373 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2374
2375 if (Sym->isVariable()) {
2376 const MCExpr *V = Sym->getVariableValue();
2377 if (!isa<MCSymbolRefExpr>(V))
2378 return ParseStatus::NoMatch;
2379 }
2380
2381 SMLoc E;
2382 if (getParser().parseExpression(Res, E))
2383 return ParseStatus::Failure;
2384
2385 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2386 return ParseStatus::Success;
2387}
2388
2389ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2390 SMLoc S = getLoc();
2391 const MCExpr *Res;
2392
2393 if (getLexer().getKind() != AsmToken::Identifier)
2394 return ParseStatus::NoMatch;
2395 std::string Identifier(getTok().getIdentifier());
2396
2397 if (getLexer().peekTok().is(AsmToken::At)) {
2398 Lex();
2399 Lex();
2400 StringRef PLT;
2401 SMLoc Loc = getLoc();
2402 if (getParser().parseIdentifier(PLT) || PLT != "plt")
2403 return Error(Loc, "@ (except the deprecated/ignored @plt) is disallowed");
2404 } else if (!getLexer().peekTok().is(AsmToken::EndOfStatement)) {
2405 // Avoid parsing the register in `call rd, foo` as a call symbol.
2406 return ParseStatus::NoMatch;
2407 } else {
2408 Lex();
2409 }
2410
2411 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
2413
2414 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2415 Res = MCSymbolRefExpr::create(Sym, getContext());
2416 Res = MCSpecifierExpr::create(Res, Kind, getContext());
2417 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2418 return ParseStatus::Success;
2419}
2420
2421ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2422 SMLoc S = getLoc();
2423 SMLoc E;
2424 const MCExpr *Res;
2425
2426 if (getParser().parseExpression(Res, E))
2427 return ParseStatus::Failure;
2428
2429 if (Res->getKind() != MCExpr::ExprKind::SymbolRef)
2430 return Error(S, "operand must be a valid jump target");
2431
2433 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2434 return ParseStatus::Success;
2435}
2436
2437ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2438 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2439 // both being acceptable forms. When parsing `jal ra, foo` this function
2440 // will be called for the `ra` register operand in an attempt to match the
2441 // single-operand alias. parseJALOffset must fail for this case. It would
2442 // seem logical to try parse the operand using parseExpression and return
2443 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2444 // the second form rather than the first). We can't do this as there's no
2445 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2446 // is an identifier and is followed by a comma.
2447 if (getLexer().is(AsmToken::Identifier) &&
2448 getLexer().peekTok().is(AsmToken::Comma))
2449 return ParseStatus::NoMatch;
2450
2451 return parseExpression(Operands);
2452}
2453
2454bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
2455 unsigned &Sew, unsigned &Lmul,
2456 bool &Fractional, bool &TailAgnostic,
2457 bool &MaskAgnostic, bool &AltFmt) {
2458 if (Tok.isNot(AsmToken::Identifier))
2459 return true;
2460
2461 StringRef Identifier = Tok.getIdentifier();
2462 if (State < VTypeState::SeenSew && Identifier.consume_front("e")) {
2463 if (Identifier.getAsInteger(10, Sew)) {
2464 if (Identifier == "16alt") {
2465 AltFmt = true;
2466 Sew = 16;
2467 } else if (Identifier == "8alt") {
2468 AltFmt = true;
2469 Sew = 8;
2470 } else {
2471 return true;
2472 }
2473 }
2474 if (!RISCVVType::isValidSEW(Sew))
2475 return true;
2476
2477 State = VTypeState::SeenSew;
2478 return false;
2479 }
2480
2481 if (State < VTypeState::SeenLmul && Identifier.consume_front("m")) {
2482 // Might arrive here if lmul and tail policy unspecified, if so we're
2483 // parsing a MaskPolicy not an LMUL.
2484 if (Identifier == "a" || Identifier == "u") {
2485 MaskAgnostic = (Identifier == "a");
2486 State = VTypeState::SeenMaskPolicy;
2487 return false;
2488 }
2489
2490 Fractional = Identifier.consume_front("f");
2491 if (Identifier.getAsInteger(10, Lmul))
2492 return true;
2493 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2494 return true;
2495
2496 if (Fractional) {
2497 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2498 unsigned MinLMUL = ELEN / 8;
2499 if (Lmul > MinLMUL)
2500 Warning(Tok.getLoc(),
2501 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2502 Twine(MinLMUL) + " is reserved");
2503 }
2504
2505 State = VTypeState::SeenLmul;
2506 return false;
2507 }
2508
2509 if (State < VTypeState::SeenTailPolicy && Identifier.starts_with("t")) {
2510 if (Identifier == "ta")
2511 TailAgnostic = true;
2512 else if (Identifier == "tu")
2513 TailAgnostic = false;
2514 else
2515 return true;
2516
2517 State = VTypeState::SeenTailPolicy;
2518 return false;
2519 }
2520
2521 if (State < VTypeState::SeenMaskPolicy && Identifier.starts_with("m")) {
2522 if (Identifier == "ma")
2523 MaskAgnostic = true;
2524 else if (Identifier == "mu")
2525 MaskAgnostic = false;
2526 else
2527 return true;
2528
2529 State = VTypeState::SeenMaskPolicy;
2530 return false;
2531 }
2532
2533 return true;
2534}
2535
2536ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2537 SMLoc S = getLoc();
2538
2539 // Default values
2540 unsigned Sew = 8;
2541 unsigned Lmul = 1;
2542 bool Fractional = false;
2543 bool TailAgnostic = false;
2544 bool MaskAgnostic = false;
2545 bool AltFmt = false;
2546
2547 VTypeState State = VTypeState::SeenNothingYet;
2548 do {
2549 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2550 MaskAgnostic, AltFmt)) {
2551 // The first time, errors return NoMatch rather than Failure
2552 if (State == VTypeState::SeenNothingYet)
2553 return ParseStatus::NoMatch;
2554 break;
2555 }
2556
2557 getLexer().Lex();
2558 } while (parseOptionalToken(AsmToken::Comma));
2559
2560 if (!getLexer().is(AsmToken::EndOfStatement) ||
2561 State == VTypeState::SeenNothingYet)
2562 return generateVTypeError(S);
2563
2565 if (Fractional) {
2566 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2567 unsigned MaxSEW = ELEN / Lmul;
2568 // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2569 if (MaxSEW >= 8 && Sew > MaxSEW)
2570 Warning(S, "use of vtype encodings with SEW > " + Twine(MaxSEW) +
2571 " and LMUL == mf" + Twine(Lmul) +
2572 " may not be compatible with all RVV implementations");
2573 }
2574
2575 unsigned VTypeI =
2576 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic, AltFmt);
2577 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2578 return ParseStatus::Success;
2579}
2580
2581bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2582 return Error(ErrorLoc,
2583 "operand must be "
2584 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2585}
2586
2587ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
2588 SMLoc S = getLoc();
2589
2590 unsigned Widen = 0;
2591 unsigned SEW = 0;
2592 bool AltFmt = false;
2593 StringRef Identifier;
2594
2595 if (getTok().isNot(AsmToken::Identifier))
2596 goto Fail;
2597
2598 Identifier = getTok().getIdentifier();
2599
2600 if (!Identifier.consume_front("e"))
2601 goto Fail;
2602
2603 if (Identifier.getAsInteger(10, SEW)) {
2604 if (Identifier != "16alt")
2605 goto Fail;
2606
2607 AltFmt = true;
2608 SEW = 16;
2609 }
2610 if (!RISCVVType::isValidSEW(SEW))
2611 goto Fail;
2612
2613 Lex();
2614
2615 if (!parseOptionalToken(AsmToken::Comma))
2616 goto Fail;
2617
2618 if (getTok().isNot(AsmToken::Identifier))
2619 goto Fail;
2620
2621 Identifier = getTok().getIdentifier();
2622
2623 if (!Identifier.consume_front("w"))
2624 goto Fail;
2625 if (Identifier.getAsInteger(10, Widen))
2626 goto Fail;
2627 if (Widen != 1 && Widen != 2 && Widen != 4)
2628 goto Fail;
2629
2630 Lex();
2631
2632 if (getLexer().is(AsmToken::EndOfStatement)) {
2633 Operands.push_back(RISCVOperand::createVType(
2634 RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
2635 return ParseStatus::Success;
2636 }
2637
2638Fail:
2639 return generateXSfmmVTypeError(S);
2640}
2641
2642bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
2643 return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");
2644}
2645
2646ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2647 if (getLexer().isNot(AsmToken::Identifier))
2648 return ParseStatus::NoMatch;
2649
2650 StringRef Name = getLexer().getTok().getIdentifier();
2651 if (!Name.consume_back(".t")) {
2652 // Non-register identifiers may belong to another optional operand in an
2653 // overloaded mnemonic. Let the matcher try those alternatives.
2654 if (matchRegisterNameHelper(Name))
2655 return Error(getLoc(), "expected '.t' suffix");
2656 return ParseStatus::NoMatch;
2657 }
2658 MCRegister Reg = matchRegisterNameHelper(Name);
2659
2660 if (!Reg)
2661 return ParseStatus::NoMatch;
2662 if (Reg != RISCV::V0)
2663 return ParseStatus::NoMatch;
2664 SMLoc S = getLoc();
2665 SMLoc E = getTok().getEndLoc();
2666 getLexer().Lex();
2667 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2668 return ParseStatus::Success;
2669}
2670
2671ParseStatus RISCVAsmParser::parseVScaleReg(OperandVector &Operands) {
2672 if (getLexer().isNot(AsmToken::Identifier))
2673 return ParseStatus::NoMatch;
2674
2675 StringRef Name = getLexer().getTok().getIdentifier();
2676 if (!Name.consume_back(".scale"))
2677 return Error(getLoc(), "expected '.scale' suffix");
2678 MCRegister Reg = matchRegisterNameHelper(Name);
2679
2680 if (!Reg)
2681 return ParseStatus::NoMatch;
2682 if (Reg != RISCV::V0)
2683 return ParseStatus::NoMatch;
2684 SMLoc S = getLoc();
2685 SMLoc E = getTok().getEndLoc();
2686 getLexer().Lex();
2687 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2688 return ParseStatus::Success;
2689}
2690
2691ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
2692 if (getLexer().isNot(AsmToken::Identifier))
2693 return ParseStatus::NoMatch;
2694
2695 SMLoc S = getLoc();
2696 StringRef Name = getLexer().getTok().getIdentifier();
2697 if (!Name.consume_front("L") && !Name.consume_front("l"))
2698 return ParseStatus::NoMatch;
2699
2700 unsigned Lambda;
2701 if (Name.getAsInteger(10, Lambda) || !isPowerOf2_32(Lambda) || Lambda >= 128)
2702 return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
2703
2704 unsigned EncodedLambda = Log2_32(Lambda) + 1;
2705
2706 SMLoc E = getTok().getEndLoc();
2707 getLexer().Lex();
2708 Operands.push_back(RISCVOperand::createExpr(
2709 MCConstantExpr::create(EncodedLambda, getContext()), S, E, isRV64()));
2710 return ParseStatus::Success;
2711}
2712
2713ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
2714 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2715 return ParseStatus::NoMatch;
2716
2717 return parseGPRAsFPR(Operands);
2718}
2719
2720ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2721 if (getLexer().isNot(AsmToken::Identifier))
2722 return ParseStatus::NoMatch;
2723
2724 StringRef Name = getLexer().getTok().getIdentifier();
2725 MCRegister Reg = matchRegisterNameHelper(Name);
2726
2727 if (!Reg)
2728 return ParseStatus::NoMatch;
2729 SMLoc S = getLoc();
2730 SMLoc E = getTok().getEndLoc();
2731 getLexer().Lex();
2732 Operands.push_back(RISCVOperand::createReg(
2733 Reg, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2734 return ParseStatus::Success;
2735}
2736
2737ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
2738 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2739 return ParseStatus::NoMatch;
2740
2741 if (getLexer().isNot(AsmToken::Identifier))
2742 return ParseStatus::NoMatch;
2743
2744 StringRef Name = getLexer().getTok().getIdentifier();
2745 MCRegister Reg = matchRegisterNameHelper(Name);
2746
2747 if (!Reg)
2748 return ParseStatus::NoMatch;
2749
2750 if (!getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg))
2751 return ParseStatus::NoMatch;
2752
2753 if ((Reg - RISCV::X0) & 1) {
2754 // Only report the even register error if we have at least Zfinx so we know
2755 // some FP is enabled. We already checked F earlier.
2756 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2757 return TokError("double precision floating point operands must use even "
2758 "numbered X register");
2759 return ParseStatus::NoMatch;
2760 }
2761
2762 SMLoc S = getLoc();
2763 SMLoc E = getTok().getEndLoc();
2764 getLexer().Lex();
2765
2766 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2767 MCRegister Pair = RI->getMatchingSuperReg(
2768 Reg, RISCV::sub_gpr_even,
2769 &getRISCVMCRegisterClass(RISCV::GPRPairRegClassID));
2770 Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));
2771 return ParseStatus::Success;
2772}
2773
2774template <bool IsRV64>
2775ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2776 return parseGPRPair(Operands, IsRV64);
2777}
2778
2779ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2780 bool IsRV64Inst) {
2781 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2782 // RV64 as it will prevent matching the RV64 version of the same instruction
2783 // that doesn't use a GPRPair.
2784 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2785 // still parse as a pair.
2786 if (!IsRV64Inst && isRV64())
2787 return ParseStatus::NoMatch;
2788
2789 if (getLexer().isNot(AsmToken::Identifier))
2790 return ParseStatus::NoMatch;
2791
2792 StringRef Name = getLexer().getTok().getIdentifier();
2793 MCRegister Reg = matchRegisterNameHelper(Name);
2794
2795 if (!Reg)
2796 return ParseStatus::NoMatch;
2797
2798 if (!getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg))
2799 return ParseStatus::NoMatch;
2800
2801 if ((Reg - RISCV::X0) & 1)
2802 return TokError("register must be even");
2803
2804 SMLoc S = getLoc();
2805 SMLoc E = getTok().getEndLoc();
2806 getLexer().Lex();
2807
2808 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2809 MCRegister Pair = RI->getMatchingSuperReg(
2810 Reg, RISCV::sub_gpr_even,
2811 &getRISCVMCRegisterClass(RISCV::GPRPairRegClassID));
2812 Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2813 return ParseStatus::Success;
2814}
2815
2816ParseStatus RISCVAsmParser::parseSMTVType(OperandVector &Operands) {
2817 if (getLexer().isNot(AsmToken::Identifier))
2818 return TokError(
2819 "operand must be a valid SpacemiT's Integer Matrix VType mnemonic");
2820
2821 StringRef Str = getLexer().getTok().getIdentifier();
2823
2824 if (!isValidSMTVTypeMode(VType))
2825 return TokError("SpacemiT's Integer Matrix only supports [i4|i8] mode");
2826
2827 Operands.push_back(RISCVOperand::createSMTVType(VType, getLoc()));
2828 Lex(); // Eat identifier token.
2829 return ParseStatus::Success;
2830}
2831
2832ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2833 if (getLexer().isNot(AsmToken::Identifier))
2834 return TokError(
2835 "operand must be a valid floating point rounding mode mnemonic");
2836
2837 StringRef Str = getLexer().getTok().getIdentifier();
2839
2840 if (FRM == RISCVFPRndMode::Invalid)
2841 return TokError(
2842 "operand must be a valid floating point rounding mode mnemonic");
2843
2844 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2845 Lex(); // Eat identifier token.
2846 return ParseStatus::Success;
2847}
2848
2849std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultSMTVType() {
2850 return RISCVOperand::createSMTVType(XSMTVTypeMode::SMTVTypeMode::SMT_I8,
2851 SMLoc());
2852}
2853
2854ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2855 const AsmToken &Tok = getLexer().getTok();
2856
2857 if (Tok.is(AsmToken::Integer)) {
2858 if (Tok.getIntVal() != 0)
2859 goto ParseFail;
2860
2861 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2862 Lex();
2863 return ParseStatus::Success;
2864 }
2865
2866 if (Tok.is(AsmToken::Identifier)) {
2867 StringRef Str = Tok.getIdentifier();
2868
2869 // Letters must be unique, taken from 'iorw', and in ascending order. This
2870 // holds as long as each individual character is one of 'iorw' and is
2871 // greater than the previous character.
2872 unsigned Imm = 0;
2873 bool Valid = true;
2874 char Prev = '\0';
2875 for (char c : Str) {
2876 switch (c) {
2877 default:
2878 Valid = false;
2879 break;
2880 case 'i':
2882 break;
2883 case 'o':
2885 break;
2886 case 'r':
2888 break;
2889 case 'w':
2891 break;
2892 }
2893
2894 if (c <= Prev) {
2895 Valid = false;
2896 break;
2897 }
2898 Prev = c;
2899 }
2900
2901 if (!Valid)
2902 goto ParseFail;
2903
2904 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2905 Lex();
2906 return ParseStatus::Success;
2907 }
2908
2909ParseFail:
2910 return TokError("operand must be formed of letters selected in-order from "
2911 "'iorw' or be 0");
2912}
2913
2914ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2915 if (parseToken(AsmToken::LParen, "expected '('"))
2916 return ParseStatus::Failure;
2917 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2918
2919 if (!parseRegister(Operands).isSuccess())
2920 return Error(getLoc(), "expected register");
2921
2922 if (parseToken(AsmToken::RParen, "expected ')'"))
2923 return ParseStatus::Failure;
2924 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2925
2926 return ParseStatus::Success;
2927}
2928
2929ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2930 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2931 // as one of their register operands, such as `(a0)`. This just denotes that
2932 // the register (in this case `a0`) contains a memory address.
2933 //
2934 // Normally, we would be able to parse these by putting the parens into the
2935 // instruction string. However, GNU as also accepts a zero-offset memory
2936 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2937 // with parseExpression followed by parseMemOpBaseReg, but these instructions
2938 // do not accept an immediate operand, and we do not want to add a "dummy"
2939 // operand that is silently dropped.
2940 //
2941 // Instead, we use this custom parser. This will: allow (and discard) an
2942 // offset if it is zero; require (and discard) parentheses; and add only the
2943 // parsed register operand to `Operands`.
2944 //
2945 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2946 // which will only print the register surrounded by parentheses (which GNU as
2947 // also uses as its canonical representation for these operands).
2948 std::unique_ptr<RISCVOperand> OptionalImmOp;
2949
2950 if (getLexer().isNot(AsmToken::LParen)) {
2951 // Parse an Integer token. We do not accept arbitrary constant expressions
2952 // in the offset field (because they may include parens, which complicates
2953 // parsing a lot).
2954 int64_t ImmVal;
2955 SMLoc ImmStart = getLoc();
2956 if (getParser().parseIntToken(ImmVal,
2957 "expected '(' or optional integer offset"))
2958 return ParseStatus::Failure;
2959
2960 // Create a RISCVOperand for checking later (so the error messages are
2961 // nicer), but we don't add it to Operands.
2962 SMLoc ImmEnd = getLoc();
2963 OptionalImmOp =
2964 RISCVOperand::createExpr(MCConstantExpr::create(ImmVal, getContext()),
2965 ImmStart, ImmEnd, isRV64());
2966 }
2967
2968 if (parseToken(AsmToken::LParen,
2969 OptionalImmOp ? "expected '(' after optional integer offset"
2970 : "expected '(' or optional integer offset"))
2971 return ParseStatus::Failure;
2972
2973 if (!parseRegister(Operands).isSuccess())
2974 return Error(getLoc(), "expected register");
2975
2976 if (parseToken(AsmToken::RParen, "expected ')'"))
2977 return ParseStatus::Failure;
2978
2979 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2980 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2981 return Error(
2982 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2983 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2984
2985 return ParseStatus::Success;
2986}
2987
2988ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2989 // RR : a2(a1)
2990 if (getLexer().getKind() != AsmToken::Identifier)
2991 return ParseStatus::NoMatch;
2992
2993 SMLoc S = getLoc();
2994 StringRef OffsetRegName = getLexer().getTok().getIdentifier();
2995 MCRegister OffsetReg = matchRegisterNameHelper(OffsetRegName);
2996 if (!OffsetReg ||
2997 !getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(OffsetReg))
2998 return Error(getLoc(), "expected GPR register");
2999 getLexer().Lex();
3000
3001 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
3002 return ParseStatus::Failure;
3003
3004 if (getLexer().getKind() != AsmToken::Identifier)
3005 return Error(getLoc(), "expected GPR register");
3006
3007 StringRef BaseRegName = getLexer().getTok().getIdentifier();
3008 MCRegister BaseReg = matchRegisterNameHelper(BaseRegName);
3009 if (!BaseReg ||
3010 !getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(BaseReg))
3011 return Error(getLoc(), "expected GPR register");
3012 getLexer().Lex();
3013
3014 if (parseToken(AsmToken::RParen, "expected ')'"))
3015 return ParseStatus::Failure;
3016
3017 Operands.push_back(RISCVOperand::createRegReg(BaseReg, OffsetReg, S));
3018
3019 return ParseStatus::Success;
3020}
3021
3022// RegList: {ra [, s0[-sN]]}
3023// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
3024
3025// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
3026// must include `fp`/`s0` in the list:
3027// RegList: {ra, s0[-sN]}
3028// XRegList: {x1, x8[-x9][, x18[-xN]]}
3029ParseStatus RISCVAsmParser::parseRegList(OperandVector &Operands,
3030 bool MustIncludeS0) {
3031 if (getTok().isNot(AsmToken::LCurly))
3032 return ParseStatus::NoMatch;
3033
3034 SMLoc S = getLoc();
3035
3036 Lex();
3037
3038 bool UsesXRegs;
3039 MCRegister RegEnd;
3040 do {
3041 if (getTok().isNot(AsmToken::Identifier))
3042 return Error(getLoc(), "invalid register");
3043
3044 StringRef RegName = getTok().getIdentifier();
3045 MCRegister Reg = matchRegisterNameHelper(RegName);
3046 if (!Reg)
3047 return Error(getLoc(), "invalid register");
3048
3049 if (!RegEnd) {
3050 UsesXRegs = RegName[0] == 'x';
3051 if (Reg != RISCV::X1)
3052 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
3053 } else if (RegEnd == RISCV::X1) {
3054 if (Reg != RISCV::X8 || (UsesXRegs != (RegName[0] == 'x')))
3055 return Error(getLoc(), Twine("register must be '") +
3056 (UsesXRegs ? "x8" : "s0") + "'");
3057 } else if (RegEnd == RISCV::X9 && UsesXRegs) {
3058 if (Reg != RISCV::X18 || (RegName[0] != 'x'))
3059 return Error(getLoc(), "register must be 'x18'");
3060 } else {
3061 return Error(getLoc(), "too many register ranges");
3062 }
3063
3064 RegEnd = Reg;
3065
3066 Lex();
3067
3068 SMLoc MinusLoc = getLoc();
3069 if (parseOptionalToken(AsmToken::Minus)) {
3070 if (RegEnd == RISCV::X1)
3071 return Error(MinusLoc, Twine("register '") + (UsesXRegs ? "x1" : "ra") +
3072 "' cannot start a multiple register range");
3073
3074 if (getTok().isNot(AsmToken::Identifier))
3075 return Error(getLoc(), "invalid register");
3076
3077 StringRef RegName = getTok().getIdentifier();
3078 MCRegister Reg = matchRegisterNameHelper(RegName);
3079 if (!Reg)
3080 return Error(getLoc(), "invalid register");
3081
3082 if (RegEnd == RISCV::X8) {
3083 if ((Reg != RISCV::X9 &&
3084 (UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||
3085 (UsesXRegs != (RegName[0] == 'x'))) {
3086 if (UsesXRegs)
3087 return Error(getLoc(), "register must be 'x9'");
3088 return Error(getLoc(), "register must be in the range 's1' to 's11'");
3089 }
3090 } else if (RegEnd == RISCV::X18) {
3091 if (Reg < RISCV::X19 || Reg > RISCV::X27 || (RegName[0] != 'x'))
3092 return Error(getLoc(),
3093 "register must be in the range 'x19' to 'x27'");
3094 } else
3095 llvm_unreachable("unexpected register");
3096
3097 RegEnd = Reg;
3098
3099 Lex();
3100 }
3101 } while (parseOptionalToken(AsmToken::Comma));
3102
3103 if (parseToken(AsmToken::RCurly, "expected ',' or '}'"))
3104 return ParseStatus::Failure;
3105
3106 if (RegEnd == RISCV::X26)
3107 return Error(S, "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
3108 "x18-x26}' is not supported");
3109
3110 auto Encode = RISCVZC::encodeRegList(RegEnd, isRVE());
3111 assert(Encode != RISCVZC::INVALID_RLIST);
3112
3113 if (MustIncludeS0 && Encode == RISCVZC::RA)
3114 return Error(S, "register list must include 's0' or 'x8'");
3115
3116 Operands.push_back(RISCVOperand::createRegList(Encode, S));
3117
3118 return ParseStatus::Success;
3119}
3120
3121ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
3122 bool ExpectNegative) {
3123 SMLoc S = getLoc();
3124 bool Negative = parseOptionalToken(AsmToken::Minus);
3125
3126 if (getTok().isNot(AsmToken::Integer))
3127 return ParseStatus::NoMatch;
3128
3129 int64_t StackAdjustment = getTok().getIntVal();
3130
3131 auto *RegListOp = static_cast<RISCVOperand *>(Operands.back().get());
3132 if (!RegListOp->isRegList())
3133 return ParseStatus::NoMatch;
3134
3135 unsigned RlistEncode = RegListOp->RegList.Encoding;
3136
3137 assert(RlistEncode != RISCVZC::INVALID_RLIST);
3138 unsigned StackAdjBase = RISCVZC::getStackAdjBase(RlistEncode, isRV64());
3139 if (Negative != ExpectNegative || StackAdjustment % 16 != 0 ||
3140 StackAdjustment < StackAdjBase || (StackAdjustment - StackAdjBase) > 48) {
3141 int64_t Lower = StackAdjBase;
3142 int64_t Upper = StackAdjBase + 48;
3143 if (ExpectNegative) {
3144 Lower = -Lower;
3145 Upper = -Upper;
3147 }
3148 return generateImmOutOfRangeError(S, Lower, Upper,
3149 "stack adjustment for register list must "
3150 "be a multiple of 16 bytes in the range");
3151 }
3152
3153 unsigned StackAdj = (StackAdjustment - StackAdjBase);
3154 Operands.push_back(RISCVOperand::createStackAdj(StackAdj, S));
3155 Lex();
3156 return ParseStatus::Success;
3157}
3158
3159/// Looks at a token type and creates the relevant operand from this
3160/// information, adding to Operands. If operand was parsed, returns false, else
3161/// true.
3162bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
3163 // Check if the current operand has a custom associated parser, if so, try to
3164 // custom parse the operand, or fallback to the general approach.
3165 ParseStatus Result =
3166 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
3167 if (Result.isSuccess())
3168 return false;
3169 if (Result.isFailure())
3170 return true;
3171
3172 // Attempt to parse token as a register.
3173 if (parseRegister(Operands, true).isSuccess())
3174 return false;
3175
3176 // Attempt to parse token as an expression
3177 if (parseExpression(Operands).isSuccess()) {
3178 // Parse memory base register if present
3179 if (getLexer().is(AsmToken::LParen))
3180 return !parseMemOpBaseReg(Operands).isSuccess();
3181 return false;
3182 }
3183
3184 // Finally we have exhausted all options and must declare defeat.
3185 Error(getLoc(), "unknown operand");
3186 return true;
3187}
3188
3189bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,
3190 StringRef Name, SMLoc NameLoc,
3192 // Apply mnemonic aliases because the destination mnemonic may have require
3193 // custom operand parsing. The generic tblgen'erated code does this later, at
3194 // the start of MatchInstructionImpl(), but that's too late for custom
3195 // operand parsing.
3196 const FeatureBitset &AvailableFeatures = getAvailableFeatures();
3197 applyMnemonicAliases(Name, AvailableFeatures, 0);
3198
3199 // First operand is token for instruction
3200 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
3201
3202 // If there are no more operands, then finish
3203 if (getLexer().is(AsmToken::EndOfStatement)) {
3204 getParser().Lex(); // Consume the EndOfStatement.
3205 return false;
3206 }
3207
3208 // Parse first operand
3209 if (parseOperand(Operands, Name))
3210 return true;
3211
3212 // Parse until end of statement, consuming commas between operands
3213 while (parseOptionalToken(AsmToken::Comma)) {
3214 // Parse next operand
3215 if (parseOperand(Operands, Name))
3216 return true;
3217 }
3218
3219 if (getParser().parseEOL("unexpected token")) {
3220 getParser().eatToEndOfStatement();
3221 return true;
3222 }
3223 return false;
3224}
3225
3226bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
3227 RISCV::Specifier &Kind) {
3229 if (const auto *RE = dyn_cast<MCSpecifierExpr>(Expr)) {
3230 Kind = RE->getSpecifier();
3231 Expr = RE->getSubExpr();
3232 }
3233
3234 MCValue Res;
3235 if (Expr->evaluateAsRelocatable(Res, nullptr))
3236 return Res.getSpecifier() == RISCV::S_None;
3237 return false;
3238}
3239
3240bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
3241 MCValue Res;
3242 if (Expr->evaluateAsRelocatable(Res, nullptr)) {
3243 return Res.getSpecifier() == RISCV::S_None && Res.getAddSym() &&
3244 Res.getSubSym();
3245 }
3246 return false;
3247}
3248
3249ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
3250 StringRef IDVal = DirectiveID.getString();
3251
3252 if (IDVal == ".option")
3253 return parseDirectiveOption();
3254 if (IDVal == ".attribute")
3255 return parseDirectiveAttribute();
3256 if (IDVal == ".insn")
3257 return parseDirectiveInsn(DirectiveID.getLoc());
3258 if (IDVal == ".variant_cc")
3259 return parseDirectiveVariantCC();
3260
3261 return ParseStatus::NoMatch;
3262}
3263
3264bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
3265 bool FromOptionDirective) {
3266 const auto &AllFeatures = getSTI().getAllProcessorFeatures();
3267 for (auto &Feature : AllFeatures)
3269 clearFeatureBits(Feature.Value, Feature.key());
3270
3271 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
3272 Arch, /*EnableExperimentalExtension=*/true,
3273 /*ExperimentalExtensionVersionCheck=*/true);
3274 if (!ParseResult) {
3275 std::string Buffer;
3276 raw_string_ostream OutputErrMsg(Buffer);
3277 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
3278 OutputErrMsg << "invalid arch name '" << Arch << "', "
3279 << ErrMsg.getMessage();
3280 });
3281
3282 return Error(Loc, OutputErrMsg.str());
3283 }
3284 auto &ISAInfo = *ParseResult;
3285
3286 for (auto &Feature : AllFeatures)
3287 if (ISAInfo->hasExtension(Feature.key()))
3288 setFeatureBits(Feature.Value, Feature.key());
3289
3290 if (FromOptionDirective) {
3291 if (ISAInfo->getXLen() == 32 && isRV64())
3292 return Error(Loc, "bad arch string switching from rv64 to rv32");
3293 else if (ISAInfo->getXLen() == 64 && !isRV64())
3294 return Error(Loc, "bad arch string switching from rv32 to rv64");
3295 }
3296
3297 if (ISAInfo->getXLen() == 32)
3298 clearFeatureBits(RISCV::Feature64Bit, "64bit");
3299 else if (ISAInfo->getXLen() == 64)
3300 setFeatureBits(RISCV::Feature64Bit, "64bit");
3301 else
3302 return Error(Loc, "bad arch string " + Arch);
3303
3304 Result = ISAInfo->toString();
3305 return false;
3306}
3307
3308bool RISCVAsmParser::parseDirectiveOption() {
3309 MCAsmParser &Parser = getParser();
3310 // Get the option token.
3311 AsmToken Tok = Parser.getTok();
3312
3313 // At the moment only identifiers are supported.
3314 if (parseToken(AsmToken::Identifier, "expected identifier"))
3315 return true;
3316
3317 StringRef Option = Tok.getIdentifier();
3318
3319 if (Option == "push") {
3320 if (Parser.parseEOL())
3321 return true;
3322
3323 getTargetStreamer().emitDirectiveOptionPush();
3324 pushFeatureBits();
3325 return false;
3326 }
3327
3328 if (Option == "pop") {
3329 SMLoc StartLoc = Parser.getTok().getLoc();
3330 if (Parser.parseEOL())
3331 return true;
3332
3333 getTargetStreamer().emitDirectiveOptionPop();
3334 if (popFeatureBits())
3335 return Error(StartLoc, ".option pop with no .option push");
3336
3337 return false;
3338 }
3339
3340 if (Option == "arch") {
3342 do {
3343 if (Parser.parseComma())
3344 return true;
3345
3347 if (parseOptionalToken(AsmToken::Plus))
3348 Type = RISCVOptionArchArgType::Plus;
3349 else if (parseOptionalToken(AsmToken::Minus))
3350 Type = RISCVOptionArchArgType::Minus;
3351 else if (!Args.empty())
3352 return Error(Parser.getTok().getLoc(),
3353 "unexpected token, expected + or -");
3354 else
3355 Type = RISCVOptionArchArgType::Full;
3356
3357 if (Parser.getTok().isNot(AsmToken::Identifier))
3358 return Error(Parser.getTok().getLoc(),
3359 "unexpected token, expected identifier");
3360
3361 StringRef Arch = Parser.getTok().getString();
3362 SMLoc Loc = Parser.getTok().getLoc();
3363 Parser.Lex();
3364
3365 if (Type == RISCVOptionArchArgType::Full) {
3366 std::string Result;
3367 if (resetToArch(Arch, Loc, Result, true))
3368 return true;
3369
3370 Args.emplace_back(Type, Result);
3371 break;
3372 }
3373
3374 if (isDigit(Arch.back()))
3375 return Error(
3376 Loc, "extension version number parsing not currently implemented");
3377
3378 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
3379 if (!enableExperimentalExtension() &&
3380 StringRef(Feature).starts_with("experimental-"))
3381 return Error(Loc, "unexpected experimental extensions");
3382 const auto &AllFeatures = getSTI().getAllProcessorFeatures();
3383 auto Ext = llvm::lower_bound(AllFeatures, Feature);
3384 if (Ext == std::end(AllFeatures) || StringRef(Ext->key()) != Feature)
3385 return Error(Loc, "unknown extension feature");
3386
3387 Args.emplace_back(Type, Arch.str());
3388
3389 if (Type == RISCVOptionArchArgType::Plus) {
3390 FeatureBitset OldFeatureBits = STI->getFeatureBits();
3391
3392 setFeatureBits(Ext->Value, Ext->key());
3393 auto ParseResult = RISCVFeatures::parseFeatureBits(*STI);
3394 if (!ParseResult) {
3395 copySTI().setFeatureBits(OldFeatureBits);
3396 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3397
3398 std::string Buffer;
3399 raw_string_ostream OutputErrMsg(Buffer);
3400 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
3401 OutputErrMsg << ErrMsg.getMessage();
3402 });
3403
3404 return Error(Loc, OutputErrMsg.str());
3405 }
3406 } else {
3407 assert(Type == RISCVOptionArchArgType::Minus);
3408 // It is invalid to disable an extension that there are other enabled
3409 // extensions depend on it.
3410 // TODO: Make use of RISCVISAInfo to handle this
3411 for (auto &Feature : AllFeatures) {
3412 if (getSTI().hasFeature(Feature.Value) &&
3413 Feature.Implies.test(Ext->Value))
3414 return Error(Loc, Twine("can't disable ") + Ext->key() +
3415 " extension; " + Feature.key() +
3416 " extension requires " + Ext->key() +
3417 " extension");
3418 }
3419
3420 clearFeatureBits(Ext->Value, Ext->key());
3421 }
3422 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
3423
3424 if (Parser.parseEOL())
3425 return true;
3426
3427 getTargetStreamer().emitDirectiveOptionArch(Args);
3428
3429 if (auto ParseResult = RISCVFeatures::parseFeatureBits(*STI))
3430 getTargetStreamer().setArchString((*ParseResult)->toString());
3431 return false;
3432 }
3433
3434 if (Option == "exact") {
3435 if (Parser.parseEOL())
3436 return true;
3437
3438 getTargetStreamer().emitDirectiveOptionExact();
3439 setFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
3440 clearFeatureBits(RISCV::FeatureRelax, "relax");
3441 return false;
3442 }
3443
3444 if (Option == "noexact") {
3445 if (Parser.parseEOL())
3446 return true;
3447
3448 getTargetStreamer().emitDirectiveOptionNoExact();
3449 clearFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
3450 setFeatureBits(RISCV::FeatureRelax, "relax");
3451 return false;
3452 }
3453
3454 if (Option == "rvc") {
3455 if (Parser.parseEOL())
3456 return true;
3457
3458 getTargetStreamer().emitDirectiveOptionRVC();
3459 setFeatureBits(RISCV::FeatureStdExtC, "c");
3460 if (auto ParseResult = RISCVFeatures::parseFeatureBits(*STI))
3461 getTargetStreamer().setArchString((*ParseResult)->toString());
3462 return false;
3463 }
3464
3465 if (Option == "norvc") {
3466 if (Parser.parseEOL())
3467 return true;
3468
3469 getTargetStreamer().emitDirectiveOptionNoRVC();
3470 clearFeatureBits(RISCV::FeatureStdExtC, "c");
3471 clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
3472 if (auto ParseResult = RISCVFeatures::parseFeatureBits(*STI))
3473 getTargetStreamer().setArchString((*ParseResult)->toString());
3474 return false;
3475 }
3476
3477 if (Option == "pic") {
3478 if (Parser.parseEOL())
3479 return true;
3480
3481 getTargetStreamer().emitDirectiveOptionPIC();
3482 ParserOptions.IsPicEnabled = true;
3483 return false;
3484 }
3485
3486 if (Option == "nopic") {
3487 if (Parser.parseEOL())
3488 return true;
3489
3490 getTargetStreamer().emitDirectiveOptionNoPIC();
3491 ParserOptions.IsPicEnabled = false;
3492 return false;
3493 }
3494
3495 if (Option == "relax") {
3496 if (Parser.parseEOL())
3497 return true;
3498
3499 getTargetStreamer().emitDirectiveOptionRelax();
3500 setFeatureBits(RISCV::FeatureRelax, "relax");
3501 return false;
3502 }
3503
3504 if (Option == "norelax") {
3505 if (Parser.parseEOL())
3506 return true;
3507
3508 getTargetStreamer().emitDirectiveOptionNoRelax();
3509 clearFeatureBits(RISCV::FeatureRelax, "relax");
3510 return false;
3511 }
3512
3513 // Unknown option.
3514 Warning(Parser.getTok().getLoc(),
3515 "unknown option, expected 'push', 'pop', "
3516 "'rvc', 'norvc', 'arch', 'relax', 'norelax', "
3517 "'exact', or 'noexact'");
3518 Parser.eatToEndOfStatement();
3519 return false;
3520}
3521
3522/// parseDirectiveAttribute
3523/// ::= .attribute expression ',' ( expression | "string" )
3524/// ::= .attribute identifier ',' ( expression | "string" )
3525bool RISCVAsmParser::parseDirectiveAttribute() {
3526 MCAsmParser &Parser = getParser();
3527 int64_t Tag;
3528 SMLoc TagLoc;
3529 TagLoc = Parser.getTok().getLoc();
3530 if (Parser.getTok().is(AsmToken::Identifier)) {
3531 StringRef Name = Parser.getTok().getIdentifier();
3532 std::optional<unsigned> Ret =
3534 if (!Ret)
3535 return Error(TagLoc, "attribute name not recognised: " + Name);
3536 Tag = *Ret;
3537 Parser.Lex();
3538 } else {
3539 const MCExpr *AttrExpr;
3540
3541 TagLoc = Parser.getTok().getLoc();
3542 if (Parser.parseExpression(AttrExpr))
3543 return true;
3544
3545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
3546 if (check(!CE, TagLoc, "expected numeric constant"))
3547 return true;
3548
3549 Tag = CE->getValue();
3550 }
3551
3552 if (Parser.parseComma())
3553 return true;
3554
3555 StringRef StringValue;
3556 int64_t IntegerValue = 0;
3557 bool IsIntegerValue = true;
3558
3559 // RISC-V attributes have a string value if the tag number is odd
3560 // and an integer value if the tag number is even.
3561 if (Tag % 2)
3562 IsIntegerValue = false;
3563
3564 SMLoc ValueExprLoc = Parser.getTok().getLoc();
3565 if (IsIntegerValue) {
3566 const MCExpr *ValueExpr;
3567 if (Parser.parseExpression(ValueExpr))
3568 return true;
3569
3570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
3571 if (!CE)
3572 return Error(ValueExprLoc, "expected numeric constant");
3573 IntegerValue = CE->getValue();
3574 } else {
3575 if (Parser.getTok().isNot(AsmToken::String))
3576 return Error(Parser.getTok().getLoc(), "expected string constant");
3577
3578 StringValue = Parser.getTok().getStringContents();
3579 Parser.Lex();
3580 }
3581
3582 if (Parser.parseEOL())
3583 return true;
3584
3585 if (IsIntegerValue)
3586 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3587 else if (Tag != RISCVAttrs::ARCH)
3588 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3589 else {
3590 std::string Result;
3591 if (resetToArch(StringValue, ValueExprLoc, Result, false))
3592 return true;
3593
3594 // Then emit the arch string.
3595 getTargetStreamer().emitTextAttribute(Tag, Result);
3596
3597 // And then update the active ISA so the next instruction-run emits
3598 // an ISA-specific mapping symbol.
3599 getTargetStreamer().setArchString(Result);
3600 }
3601
3602 return false;
3603}
3604
3606 return StringSwitch<bool>(Format)
3607 .Cases({"r", "r4", "i", "b", "sb", "u", "j", "uj", "s"}, true)
3608 .Cases({"cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj"},
3609 STI.hasFeature(RISCV::FeatureStdExtZca))
3610 .Cases({"qc.eai", "qc.ei", "qc.eb", "qc.ej", "qc.es"},
3611 !STI.hasFeature(RISCV::Feature64Bit))
3612 .Default(false);
3613}
3614
3615/// parseDirectiveInsn
3616/// ::= .insn [ format encoding, (operands (, operands)*) ]
3617/// ::= .insn [ length, value ]
3618/// ::= .insn [ value ]
3619bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3620 MCAsmParser &Parser = getParser();
3621
3622 // Expect instruction format as identifier.
3623 StringRef Format;
3624 SMLoc ErrorLoc = Parser.getTok().getLoc();
3625 if (Parser.parseIdentifier(Format)) {
3626 // Try parsing .insn [ length , ] value
3627 std::optional<int64_t> Length;
3628 int64_t Value = 0;
3629 if (Parser.parseAbsoluteExpression(Value))
3630 return true;
3631 if (Parser.parseOptionalToken(AsmToken::Comma)) {
3632 Length = Value;
3633 if (Parser.parseAbsoluteExpression(Value))
3634 return true;
3635
3636 if (*Length == 0 || (*Length % 2) != 0)
3637 return Error(ErrorLoc,
3638 "instruction lengths must be a non-zero multiple of two");
3639
3640 // TODO: Support Instructions > 64 bits.
3641 if (*Length > 8)
3642 return Error(ErrorLoc,
3643 "instruction lengths over 64 bits are not supported");
3644 }
3645
3646 // We only derive a length from the encoding for 16- and 32-bit
3647 // instructions, as the encodings for longer instructions are not frozen in
3648 // the spec.
3649 int64_t EncodingDerivedLength = ((Value & 0b11) == 0b11) ? 4 : 2;
3650
3651 if (Length) {
3652 // Only check the length against the encoding if the length is present and
3653 // could match
3654 if ((*Length <= 4) && (*Length != EncodingDerivedLength))
3655 return Error(ErrorLoc,
3656 "instruction length does not match the encoding");
3657
3658 if (!isUIntN(*Length * 8, Value))
3659 return Error(ErrorLoc, "encoding value does not fit into instruction");
3660 } else {
3661 if (!isUIntN(EncodingDerivedLength * 8, Value))
3662 return Error(ErrorLoc, "encoding value does not fit into instruction");
3663 }
3664
3665 if (!getSTI().hasFeature(RISCV::FeatureStdExtZca) &&
3666 (EncodingDerivedLength == 2))
3667 return Error(ErrorLoc, "compressed instructions are not allowed");
3668
3669 if (getParser().parseEOL("invalid operand for instruction")) {
3670 getParser().eatToEndOfStatement();
3671 return true;
3672 }
3673
3674 unsigned Opcode;
3675 if (Length) {
3676 switch (*Length) {
3677 case 2:
3678 Opcode = RISCV::Insn16;
3679 break;
3680 case 4:
3681 Opcode = RISCV::Insn32;
3682 break;
3683 case 6:
3684 Opcode = RISCV::Insn48;
3685 break;
3686 case 8:
3687 Opcode = RISCV::Insn64;
3688 break;
3689 default:
3690 llvm_unreachable("Error should have already been emitted");
3691 }
3692 } else
3693 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3694
3695 emitToStreamer(getStreamer(), MCInstBuilder(Opcode).addImm(Value));
3696 return false;
3697 }
3698
3699 if (!isValidInsnFormat(Format, getSTI()))
3700 return Error(ErrorLoc, "invalid instruction format");
3701
3702 std::string FormatName = (".insn_" + Format).str();
3703
3704 ParseInstructionInfo Info;
3706
3707 if (parseInstruction(Info, FormatName, L, Operands))
3708 return true;
3709
3710 unsigned Opcode;
3711 uint64_t ErrorInfo;
3712 return matchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3713 ErrorInfo,
3714 /*MatchingInlineAsm=*/false);
3715}
3716
3717/// parseDirectiveVariantCC
3718/// ::= .variant_cc symbol
3719bool RISCVAsmParser::parseDirectiveVariantCC() {
3720 StringRef Name;
3721 if (getParser().parseIdentifier(Name))
3722 return TokError("expected symbol name");
3723 if (parseEOL())
3724 return true;
3725 getTargetStreamer().emitDirectiveVariantCC(
3726 *getContext().getOrCreateSymbol(Name));
3727 return false;
3728}
3729
3730void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3731 MCInst CInst;
3732 bool Res = false;
3733 const MCSubtargetInfo &STI = getSTI();
3734 if (!STI.hasFeature(RISCV::FeatureExactAssembly))
3735 Res = RISCVRVC::compress(CInst, Inst, STI);
3736 if (Res)
3737 ++RISCVNumInstrsCompressed;
3738 S.emitInstruction((Res ? CInst : Inst), STI);
3739}
3740
3741void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3742 MCStreamer &Out) {
3744 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
3745
3746 for (MCInst &Inst : Seq) {
3747 emitToStreamer(Out, Inst);
3748 }
3749}
3750
3751void RISCVAsmParser::emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,
3752 const MCExpr *Symbol,
3753 RISCV::Specifier VKHi,
3754 unsigned SecondOpcode, SMLoc IDLoc,
3755 MCStreamer &Out) {
3756 // A pair of instructions for PC-relative addressing; expands to
3757 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3758 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3759 MCContext &Ctx = getContext();
3760
3761 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3762 Out.emitLabel(TmpLabel);
3763
3764 const auto *SymbolHi = MCSpecifierExpr::create(Symbol, VKHi, Ctx);
3765 emitToStreamer(Out,
3766 MCInstBuilder(RISCV::AUIPC).addReg(TmpReg).addExpr(SymbolHi));
3767
3768 const MCExpr *RefToLinkTmpLabel = MCSpecifierExpr::create(
3769 MCSymbolRefExpr::create(TmpLabel, Ctx), RISCV::S_PCREL_LO, Ctx);
3770
3771 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3772 .addReg(DestReg)
3773 .addReg(TmpReg)
3774 .addExpr(RefToLinkTmpLabel));
3775}
3776
3777void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3778 MCStreamer &Out) {
3779 // The load local address pseudo-instruction "lla" is used in PC-relative
3780 // addressing of local symbols:
3781 // lla rdest, symbol
3782 // expands to
3783 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3784 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3785 MCRegister DestReg = Inst.getOperand(0).getReg();
3786 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3787 if (STI->hasFeature(RISCV::Feature32Bit) &&
3788 STI->hasFeature(RISCV::FeatureVendorXqcili))
3789 emitToStreamer(
3790 Out, MCInstBuilder(RISCV::QC_E_LI).addReg(DestReg).addExpr(Symbol));
3791 else
3792 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCV::S_PCREL_HI, RISCV::ADDI,
3793 IDLoc, Out);
3794}
3795
3796void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3797 MCStreamer &Out) {
3798 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3799 // addressing of global symbols:
3800 // lga rdest, symbol
3801 // expands to
3802 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3803 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3804 MCRegister DestReg = Inst.getOperand(0).getReg();
3805 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3806 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3807 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCV::S_GOT_HI, SecondOpcode,
3808 IDLoc, Out);
3809}
3810
3811void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3812 MCStreamer &Out) {
3813 // The load address pseudo-instruction "la" is used in PC-relative and
3814 // GOT-indirect addressing of global symbols:
3815 // la rdest, symbol
3816 // is an alias for either (for non-PIC)
3817 // lla rdest, symbol
3818 // or (for PIC)
3819 // lga rdest, symbol
3820 if (ParserOptions.IsPicEnabled)
3821 emitLoadGlobalAddress(Inst, IDLoc, Out);
3822 else
3823 emitLoadLocalAddress(Inst, IDLoc, Out);
3824}
3825
3826void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3827 MCStreamer &Out) {
3828 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3829 // initial-exec TLS model addressing of global symbols:
3830 // la.tls.ie rdest, symbol
3831 // expands to
3832 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3833 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3834 MCRegister DestReg = Inst.getOperand(0).getReg();
3835 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3836 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3837 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GOT_HI20,
3838 SecondOpcode, IDLoc, Out);
3839}
3840
3841void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3842 MCStreamer &Out) {
3843 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3844 // global-dynamic TLS model addressing of global symbols:
3845 // la.tls.gd rdest, symbol
3846 // expands to
3847 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3848 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3849 MCRegister DestReg = Inst.getOperand(0).getReg();
3850 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3851 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GD_HI20,
3852 RISCV::ADDI, IDLoc, Out);
3853}
3854
3855void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3856 SMLoc IDLoc, MCStreamer &Out,
3857 bool HasTmpReg) {
3858 // The load/store pseudo-instruction does a pc-relative load with
3859 // a symbol.
3860 //
3861 // The expansion looks like this
3862 //
3863 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3864 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3865 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3866 MCRegister DestReg = Inst.getOperand(DestRegOpIdx).getReg();
3867 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3868 MCRegister TmpReg = Inst.getOperand(0).getReg();
3869
3870 // If TmpReg is a GPR pair, get the even register.
3871 if (getRISCVMCRegisterClass(RISCV::GPRPairRegClassID).contains(TmpReg)) {
3872 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3873 TmpReg = RI->getSubReg(TmpReg, RISCV::sub_gpr_even);
3874 }
3875
3876 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3877 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCV::S_PCREL_HI, Opcode, IDLoc,
3878 Out);
3879}
3880
3881void RISCVAsmParser::emitQCELILoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3882 SMLoc IDLoc, MCStreamer &Out,
3883 bool HasTmpReg) {
3884 // For loads (HasTmpReg=false): operands are [rd, symbol]
3885 // qc.e.li rd, symbol
3886 // lx rd, 0(rd), %qc.access(symbol) [possibly compressed]
3887 //
3888 // For stores (HasTmpReg=true): operands are [rt, rs, symbol]
3889 // qc.e.li rt, symbol
3890 // sx rs, 0(rt), %qc.access(symbol) [possibly compressed]
3891 MCRegister AddrReg = Inst.getOperand(0).getReg();
3892 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3893 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3894
3895 emitToStreamer(Out,
3896 MCInstBuilder(RISCV::QC_E_LI).addReg(AddrReg).addExpr(Symbol));
3897
3898 MCContext &Ctx = getContext();
3899 const MCExpr *AccessExpr =
3901
3902 // We have to manually compress the QCAccess pseudos as the current
3903 // CompressPat mechanism does not support them. Each entry pairs the
3904 // compressed opcode with the subtarget feature it requires.
3905 struct CompressedForm {
3906 unsigned Opcode;
3907 unsigned Feature;
3908 };
3909 std::optional<CompressedForm> Compressed;
3910 switch (Opcode) {
3911 default:
3912 break;
3913 case RISCV::PseudoQCAccessLBU:
3914 Compressed = {RISCV::PseudoQCAccessC_LBU, RISCV::FeatureStdExtZcb};
3915 break;
3916 case RISCV::PseudoQCAccessLH:
3917 Compressed = {RISCV::PseudoQCAccessC_LH, RISCV::FeatureStdExtZcb};
3918 break;
3919 case RISCV::PseudoQCAccessLHU:
3920 Compressed = {RISCV::PseudoQCAccessC_LHU, RISCV::FeatureStdExtZcb};
3921 break;
3922 case RISCV::PseudoQCAccessLW:
3923 Compressed = {RISCV::PseudoQCAccessC_LW, RISCV::FeatureStdExtZca};
3924 break;
3925 case RISCV::PseudoQCAccessSB:
3926 Compressed = {RISCV::PseudoQCAccessC_SB, RISCV::FeatureStdExtZcb};
3927 break;
3928 case RISCV::PseudoQCAccessSH:
3929 Compressed = {RISCV::PseudoQCAccessC_SH, RISCV::FeatureStdExtZcb};
3930 break;
3931 case RISCV::PseudoQCAccessSW:
3932 Compressed = {RISCV::PseudoQCAccessC_SW, RISCV::FeatureStdExtZca};
3933 break;
3934 }
3935
3936 // For stores, both the data register and the address register must be in
3937 // GPRC for the compressed form; for loads AddrReg serves as both.
3938 bool CanUseGPRC =
3939 getRISCVMCRegisterClass(RISCV::GPRCRegClassID).contains(AddrReg);
3940 if (HasTmpReg && CanUseGPRC) {
3941 MCRegister DataReg = Inst.getOperand(1).getReg();
3942 CanUseGPRC =
3943 getRISCVMCRegisterClass(RISCV::GPRCRegClassID).contains(DataReg);
3944 }
3945
3946 bool UseCompressed =
3947 Compressed && getSTI().hasFeature(Compressed->Feature) && CanUseGPRC;
3948
3949 unsigned ActualOpcode = UseCompressed ? Compressed->Opcode : Opcode;
3950 if (HasTmpReg) {
3951 MCRegister DataReg = Inst.getOperand(1).getReg();
3952 emitToStreamer(Out, MCInstBuilder(ActualOpcode)
3953 .addReg(DataReg)
3954 .addReg(AddrReg)
3955 .addImm(0)
3956 .addExpr(AccessExpr));
3957 } else {
3958 emitToStreamer(Out, MCInstBuilder(ActualOpcode)
3959 .addReg(AddrReg)
3960 .addReg(AddrReg)
3961 .addImm(0)
3962 .addExpr(AccessExpr));
3963 }
3964}
3965
3966void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3967 int64_t Width, SMLoc IDLoc,
3968 MCStreamer &Out) {
3969 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3970 // amounts dependent on the XLEN.
3971 //
3972 // The expansion looks like this
3973 //
3974 // SLLI rd, rs, XLEN - Width
3975 // SR[A|R]I rd, rd, XLEN - Width
3976 const MCOperand &DestReg = Inst.getOperand(0);
3977 const MCOperand &SourceReg = Inst.getOperand(1);
3978
3979 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3980 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3981
3982 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3983
3984 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3985 .addOperand(DestReg)
3986 .addOperand(SourceReg)
3987 .addImm(ShAmt));
3988
3989 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3990 .addOperand(DestReg)
3991 .addOperand(DestReg)
3992 .addImm(ShAmt));
3993}
3994
3995void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3996 MCStreamer &Out) {
3997 if (Inst.getNumOperands() == 4 && !Inst.getOperand(3).getReg()) {
3998 // unmasked va >= x
3999 //
4000 // pseudoinstruction: vmsge{u}.vx vd, va, x
4001 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
4002 emitToStreamer(Out, MCInstBuilder(Opcode)
4003 .addOperand(Inst.getOperand(0))
4004 .addOperand(Inst.getOperand(1))
4005 .addOperand(Inst.getOperand(2))
4006 .addReg(MCRegister())
4007 .setLoc(IDLoc));
4008 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
4009 .addOperand(Inst.getOperand(0))
4010 .addOperand(Inst.getOperand(0))
4011 .addOperand(Inst.getOperand(0))
4012 .setLoc(IDLoc));
4013 } else if (Inst.getNumOperands() == 4) {
4014 // masked va >= x, vd != v0
4015 //
4016 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
4017 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
4018 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
4019 "The destination register should not be V0.");
4020 assert(Inst.getOperand(3).getReg() == RISCV::V0 && "Expected a mask");
4021 emitToStreamer(Out, MCInstBuilder(Opcode)
4022 .addOperand(Inst.getOperand(0))
4023 .addOperand(Inst.getOperand(1))
4024 .addOperand(Inst.getOperand(2))
4025 .addOperand(Inst.getOperand(3))
4026 .setLoc(IDLoc));
4027 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
4028 .addOperand(Inst.getOperand(0))
4029 .addOperand(Inst.getOperand(0))
4030 .addReg(RISCV::V0)
4031 .setLoc(IDLoc));
4032 } else if (Inst.getNumOperands() == 5 &&
4033 Inst.getOperand(0).getReg() == RISCV::V0) {
4034 // masked va >= x, vd == v0
4035 //
4036 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
4037 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
4038 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
4039 "The temporary vector register should not be V0.");
4040 emitToStreamer(Out, MCInstBuilder(Opcode)
4041 .addOperand(Inst.getOperand(1))
4042 .addOperand(Inst.getOperand(2))
4043 .addOperand(Inst.getOperand(3))
4044 .addReg(MCRegister())
4045 .setLoc(IDLoc));
4046 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
4047 .addOperand(Inst.getOperand(0))
4048 .addOperand(Inst.getOperand(0))
4049 .addOperand(Inst.getOperand(1))
4050 .setLoc(IDLoc));
4051 } else if (Inst.getNumOperands() == 5) {
4052 // masked va >= x, any vd
4053 //
4054 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
4055 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
4056 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
4057 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
4058 "The temporary vector register should not be V0.");
4059 emitToStreamer(Out, MCInstBuilder(Opcode)
4060 .addOperand(Inst.getOperand(1))
4061 .addOperand(Inst.getOperand(2))
4062 .addOperand(Inst.getOperand(3))
4063 .addReg(MCRegister())
4064 .setLoc(IDLoc));
4065 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
4066 .addOperand(Inst.getOperand(1))
4067 .addReg(RISCV::V0)
4068 .addOperand(Inst.getOperand(1))
4069 .setLoc(IDLoc));
4070 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
4071 .addOperand(Inst.getOperand(0))
4072 .addOperand(Inst.getOperand(0))
4073 .addReg(RISCV::V0)
4074 .setLoc(IDLoc));
4075 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
4076 .addOperand(Inst.getOperand(0))
4077 .addOperand(Inst.getOperand(1))
4078 .addOperand(Inst.getOperand(0))
4079 .setLoc(IDLoc));
4080 }
4081}
4082
4083bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
4085 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
4086 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
4087 if (Inst.getOperand(2).getReg() != RISCV::X4) {
4088 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
4089 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
4090 "%tprel_add specifier");
4091 }
4092
4093 return false;
4094}
4095
4096bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
4098 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
4099 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
4100 if (Inst.getOperand(0).getReg() != RISCV::X5) {
4101 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
4102 return Error(ErrorLoc, "the output operand must be t0/x5 when using "
4103 "%tlsdesc_call specifier");
4104 }
4105
4106 return false;
4107}
4108
4109std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
4110 return RISCVOperand::createReg(MCRegister(), llvm::SMLoc(), llvm::SMLoc());
4111}
4112
4113std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
4114 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
4115 llvm::SMLoc());
4116}
4117
4118std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
4119 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
4120 llvm::SMLoc());
4121}
4122
4123std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultZeroOffset() {
4124 return RISCVOperand::createExpr(MCConstantExpr::create(0, getContext()),
4125 llvm::SMLoc(), llvm::SMLoc(), isRV64());
4126}
4127
4128static unsigned getNFforLXSEG(unsigned Opcode) {
4129 switch (Opcode) {
4130 default:
4131 return 1;
4132 case RISCV::VLOXSEG2EI8_V:
4133 case RISCV::VLOXSEG2EI16_V:
4134 case RISCV::VLOXSEG2EI32_V:
4135 case RISCV::VLOXSEG2EI64_V:
4136 case RISCV::VLUXSEG2EI8_V:
4137 case RISCV::VLUXSEG2EI16_V:
4138 case RISCV::VLUXSEG2EI32_V:
4139 case RISCV::VLUXSEG2EI64_V:
4140 return 2;
4141 case RISCV::VLOXSEG3EI8_V:
4142 case RISCV::VLOXSEG3EI16_V:
4143 case RISCV::VLOXSEG3EI32_V:
4144 case RISCV::VLOXSEG3EI64_V:
4145 case RISCV::VLUXSEG3EI8_V:
4146 case RISCV::VLUXSEG3EI16_V:
4147 case RISCV::VLUXSEG3EI32_V:
4148 case RISCV::VLUXSEG3EI64_V:
4149 return 3;
4150 case RISCV::VLOXSEG4EI8_V:
4151 case RISCV::VLOXSEG4EI16_V:
4152 case RISCV::VLOXSEG4EI32_V:
4153 case RISCV::VLOXSEG4EI64_V:
4154 case RISCV::VLUXSEG4EI8_V:
4155 case RISCV::VLUXSEG4EI16_V:
4156 case RISCV::VLUXSEG4EI32_V:
4157 case RISCV::VLUXSEG4EI64_V:
4158 return 4;
4159 case RISCV::VLOXSEG5EI8_V:
4160 case RISCV::VLOXSEG5EI16_V:
4161 case RISCV::VLOXSEG5EI32_V:
4162 case RISCV::VLOXSEG5EI64_V:
4163 case RISCV::VLUXSEG5EI8_V:
4164 case RISCV::VLUXSEG5EI16_V:
4165 case RISCV::VLUXSEG5EI32_V:
4166 case RISCV::VLUXSEG5EI64_V:
4167 return 5;
4168 case RISCV::VLOXSEG6EI8_V:
4169 case RISCV::VLOXSEG6EI16_V:
4170 case RISCV::VLOXSEG6EI32_V:
4171 case RISCV::VLOXSEG6EI64_V:
4172 case RISCV::VLUXSEG6EI8_V:
4173 case RISCV::VLUXSEG6EI16_V:
4174 case RISCV::VLUXSEG6EI32_V:
4175 case RISCV::VLUXSEG6EI64_V:
4176 return 6;
4177 case RISCV::VLOXSEG7EI8_V:
4178 case RISCV::VLOXSEG7EI16_V:
4179 case RISCV::VLOXSEG7EI32_V:
4180 case RISCV::VLOXSEG7EI64_V:
4181 case RISCV::VLUXSEG7EI8_V:
4182 case RISCV::VLUXSEG7EI16_V:
4183 case RISCV::VLUXSEG7EI32_V:
4184 case RISCV::VLUXSEG7EI64_V:
4185 return 7;
4186 case RISCV::VLOXSEG8EI8_V:
4187 case RISCV::VLOXSEG8EI16_V:
4188 case RISCV::VLOXSEG8EI32_V:
4189 case RISCV::VLOXSEG8EI64_V:
4190 case RISCV::VLUXSEG8EI8_V:
4191 case RISCV::VLUXSEG8EI16_V:
4192 case RISCV::VLUXSEG8EI32_V:
4193 case RISCV::VLUXSEG8EI64_V:
4194 return 8;
4195 }
4196}
4197
4199 if (getRISCVMCRegisterClass(RISCV::VRM2RegClassID).contains(Reg))
4200 return 2;
4201 if (getRISCVMCRegisterClass(RISCV::VRM4RegClassID).contains(Reg))
4202 return 4;
4203 if (getRISCVMCRegisterClass(RISCV::VRM8RegClassID).contains(Reg))
4204 return 8;
4205 return 1;
4206}
4207
4208static bool isZvvfmmScaleOpcode(unsigned Opcode) {
4209 switch (Opcode) {
4210 case RISCV::VFWMMACC_VV_SCALE:
4211 case RISCV::VFQMMACC_VV_SCALE:
4212 case RISCV::VF8WMMACC_VV_SCALE:
4213 case RISCV::VFWIMMACC_VV:
4214 case RISCV::VFQIMMACC_VV:
4215 case RISCV::VF8WIMMACC_VV:
4216 return true;
4217 default:
4218 return false;
4219 }
4220}
4221
4222bool RISCVAsmParser::validateInstruction(MCInst &Inst,
4224 unsigned Opcode = Inst.getOpcode();
4225
4226 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
4227 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
4228 MCRegister DestReg = Inst.getOperand(0).getReg();
4229 MCRegister TempReg = Inst.getOperand(1).getReg();
4230 if (DestReg == TempReg) {
4231 SMLoc Loc = Operands.back()->getStartLoc();
4232 return Error(Loc, "the temporary vector register cannot be the same as "
4233 "the destination register");
4234 }
4235 }
4236
4237 if (Opcode == RISCV::PseudoVMSGEU_VX_M || Opcode == RISCV::PseudoVMSGE_VX_M) {
4238 MCRegister DestReg = Inst.getOperand(0).getReg();
4239 MCRegister MaskReg = Inst.getOperand(3).getReg();
4240 if (MaskReg == RISCV::V0 && DestReg == RISCV::V0) {
4241 SMLoc Loc = Operands.back()->getStartLoc();
4242 return Error(Loc, "the destination vector register cannot overlap the "
4243 "mask register unless a temporary register is "
4244 "provided");
4245 }
4246 }
4247
4248 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
4249 Opcode == RISCV::TH_LWD) {
4250 MCRegister Rd1 = Inst.getOperand(0).getReg();
4251 MCRegister Rd2 = Inst.getOperand(1).getReg();
4252 MCRegister Rs1 = Inst.getOperand(2).getReg();
4253 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
4254 if (Rs1 == Rd1 || Rs1 == Rd2 || Rd1 == Rd2) {
4255 SMLoc Loc = Operands[1]->getStartLoc();
4256 return Error(Loc, "rs1, rd1, and rd2 cannot overlap");
4257 }
4258 }
4259
4260 if (Opcode == RISCV::CM_MVSA01 || Opcode == RISCV::QC_CM_MVSA01) {
4261 MCRegister Rs1 = Inst.getOperand(0).getReg();
4262 MCRegister Rs2 = Inst.getOperand(1).getReg();
4263 if (Rs1 == Rs2) {
4264 SMLoc Loc = Operands[1]->getStartLoc();
4265 return Error(Loc, "rs1 and rs2 must be different");
4266 }
4267 }
4268
4269 if (isZvvfmmScaleOpcode(Opcode)) {
4270 auto CheckOperandDoesNotOverlapV0 = [&](int OperandIdx,
4271 unsigned ParsedIdx) {
4272 if (Inst.getOperand(OperandIdx).getReg() == RISCV::V0)
4273 return Error(Operands[ParsedIdx]->getStartLoc(),
4274 "vd, vs1, and vs2 cannot overlap v0.scale");
4275 return false;
4276 };
4277
4278 int DestIdx =
4279 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
4280 int VS1Idx =
4281 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
4282 int VS2Idx =
4283 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
4284 assert(DestIdx >= 0 && VS1Idx >= 0 && VS2Idx >= 0 &&
4285 "Unexpected Zvvfmm scaled operand list");
4286
4287 if (CheckOperandDoesNotOverlapV0(DestIdx, 1) ||
4288 CheckOperandDoesNotOverlapV0(VS1Idx, 2) ||
4289 CheckOperandDoesNotOverlapV0(VS2Idx, 3))
4290 return true;
4291 }
4292
4293 const MCInstrDesc &MCID = MII.get(Opcode);
4294 if (!(MCID.TSFlags & RISCVII::RVVConstraintMask))
4295 return false;
4296
4297 int DestIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
4298 MCRegister DestReg = Inst.getOperand(DestIdx).getReg();
4299
4300 // Operands[1] or Operands[2] will be the first operand, DestReg.
4301 const MCParsedAsmOperand *ParsedOp = Operands[1].get();
4302 if (!ParsedOp->isReg()) {
4303 // XSfvcp instructions may have an immediate before vd.
4304 // FIXME: Is there a better way to do this?
4305 ParsedOp = Operands[2].get();
4306 }
4307 assert(ParsedOp->getReg() == DestReg && "Can't find parsed dest operand");
4308 SMLoc Loc = ParsedOp->getStartLoc();
4309
4310 unsigned Lmul = getLMULFromVectorRegister(DestReg);
4311 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4312 unsigned DestEncoding = RI->getEncodingValue(DestReg);
4313 if (MCID.TSFlags & RISCVII::VS2Constraint) {
4314 int VS2Idx =
4315 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
4316 assert(VS2Idx >= 0 && "No vs2 operand?");
4317 unsigned CheckEncoding =
4318 RI->getEncodingValue(Inst.getOperand(VS2Idx).getReg());
4319 unsigned NF = getNFforLXSEG(Opcode);
4320 for (unsigned i = 0; i < std::max(NF, Lmul); i++) {
4321 if ((DestEncoding + i) == CheckEncoding)
4322 return Error(Loc, "the destination vector register group cannot overlap"
4323 " the source vector register group");
4324 }
4325 }
4326 if (MCID.TSFlags & RISCVII::VS1Constraint) {
4327 int VS1Idx =
4328 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
4329 // FIXME: The vs1 constraint is used on scalar and imm instructions so we
4330 // need to check that the operand exists.
4331 if (VS1Idx >= 0) {
4332 unsigned CheckEncoding =
4333 RI->getEncodingValue(Inst.getOperand(VS1Idx).getReg());
4334 for (unsigned i = 0; i < Lmul; i++) {
4335 if ((DestEncoding + i) == CheckEncoding)
4336 return Error(Loc,
4337 "the destination vector register group cannot overlap"
4338 " the source vector register group");
4339 }
4340 }
4341 }
4342
4343 if (MCID.TSFlags & RISCVII::VMConstraint) {
4344 int VMIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vm);
4345 assert(VMIdx >= 0 && "No vm operand?");
4346
4347 if (DestReg == RISCV::V0) {
4348 if (MCID.operands()[Inst.getNumOperands() - 1].OperandType !=
4350 return Error(Loc, "the destination vector register group cannot be V0");
4351
4352 // Regardless masked or unmasked version, the number of operands is the
4353 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
4354 // actually. We need to check the operand to see whether it is masked or
4355 // not.
4356 MCRegister CheckReg = Inst.getOperand(VMIdx).getReg();
4357 assert((!CheckReg.isValid() || CheckReg == RISCV::V0) &&
4358 "Unexpected mask operand register");
4359 if (CheckReg.isValid())
4360 return Error(Loc, "the destination vector register group cannot overlap"
4361 " the mask register");
4362 }
4363 }
4364
4366 // smt.vmadot with sp and hp: the vmask operand (only use V0 or V1) must not
4367 // overlap with any of vd, vs1, or vs2.
4368 int VMaskIdx =
4369 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vmask);
4370 MCRegister MaskReg = Inst.getOperand(VMaskIdx).getReg();
4371 if (MaskReg != RISCV::V0 && MaskReg != RISCV::V1)
4372 return Error(Operands[VMaskIdx]->getStartLoc(),
4373 "vmask operand only supports v0 or v1");
4374
4375 unsigned MaskEnc = RI->getEncodingValue(MaskReg);
4376 RISCV::OpName RegOps[] = {RISCV::OpName::vd, RISCV::OpName::vs1,
4377 RISCV::OpName::vs2};
4378 for (RISCV::OpName OpN : RegOps) {
4379 int Idx = RISCV::getNamedOperandIdx(Inst.getOpcode(), OpN);
4380 if (Idx < 0 || !Inst.getOperand(Idx).isReg())
4381 continue;
4382 MCRegister Reg = Inst.getOperand(Idx).getReg();
4383 unsigned RegEnc = RI->getEncodingValue(Reg);
4384 unsigned RegLmul = getLMULFromVectorRegister(Reg);
4385 for (unsigned i = 0; i < RegLmul; i++) {
4386 if ((RegEnc + i) == MaskEnc) {
4387 SMLoc Loc = Operands[Idx]->getStartLoc();
4388 return Error(Loc, Twine("register conflicts with vmask register ") +
4390 }
4391 }
4392 }
4393 }
4394
4395 return false;
4396}
4397
4398bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
4400 MCStreamer &Out) {
4401 Inst.setLoc(IDLoc);
4402
4403 switch (Inst.getOpcode()) {
4404 default:
4405 break;
4406 case RISCV::PseudoC_ADDI_NOP: {
4407 if (Inst.getOperand(2).getImm() == 0)
4408 emitToStreamer(Out, MCInstBuilder(RISCV::C_NOP));
4409 else
4410 emitToStreamer(
4411 Out, MCInstBuilder(RISCV::C_NOP_HINT).addOperand(Inst.getOperand(2)));
4412 return false;
4413 }
4414 case RISCV::PACK: {
4415 // Convert PACK wth RS2==X0 to ZEXT_H_RV32 to match disassembler output.
4416 if (Inst.getOperand(2).getReg() != RISCV::X0)
4417 break;
4418 if (getSTI().hasFeature(RISCV::Feature64Bit))
4419 break;
4420 emitToStreamer(Out, MCInstBuilder(RISCV::ZEXT_H_RV32)
4421 .addOperand(Inst.getOperand(0))
4422 .addOperand(Inst.getOperand(1)));
4423 return false;
4424 }
4425 case RISCV::PACKW: {
4426 // Convert PACKW with RS2==X0 to ZEXT_H_RV64 to match disassembler output.
4427 if (Inst.getOperand(2).getReg() != RISCV::X0)
4428 break;
4429 emitToStreamer(Out, MCInstBuilder(RISCV::ZEXT_H_RV64)
4430 .addOperand(Inst.getOperand(0))
4431 .addOperand(Inst.getOperand(1)));
4432 return false;
4433 }
4434 case RISCV::PseudoLLAImm:
4435 case RISCV::PseudoLAImm:
4436 case RISCV::PseudoLI: {
4437 MCRegister Reg = Inst.getOperand(0).getReg();
4438 const MCOperand &Op1 = Inst.getOperand(1);
4439 if (Op1.isExpr()) {
4440 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
4441 // Just convert to an addi. This allows compatibility with gas.
4442 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
4443 .addReg(Reg)
4444 .addReg(RISCV::X0)
4445 .addExpr(Op1.getExpr()));
4446 return false;
4447 }
4448 int64_t Imm = Inst.getOperand(1).getImm();
4449 // On RV32 the immediate here can either be a signed or an unsigned
4450 // 32-bit number. Sign extension has to be performed to ensure that Imm
4451 // represents the expected signed 64-bit number.
4452 if (!isRV64())
4453 Imm = SignExtend64<32>(Imm);
4454 emitLoadImm(Reg, Imm, Out);
4455 return false;
4456 }
4457 case RISCV::PseudoLLA:
4458 emitLoadLocalAddress(Inst, IDLoc, Out);
4459 return false;
4460 case RISCV::PseudoLGA:
4461 emitLoadGlobalAddress(Inst, IDLoc, Out);
4462 return false;
4463 case RISCV::PseudoLA:
4464 emitLoadAddress(Inst, IDLoc, Out);
4465 return false;
4466 case RISCV::PseudoLA_TLS_IE:
4467 emitLoadTLSIEAddress(Inst, IDLoc, Out);
4468 return false;
4469 case RISCV::PseudoLA_TLS_GD:
4470 emitLoadTLSGDAddress(Inst, IDLoc, Out);
4471 return false;
4472 case RISCV::PseudoLB:
4473 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
4474 return false;
4475 case RISCV::PseudoLBU:
4476 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
4477 return false;
4478 case RISCV::PseudoLH:
4479 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
4480 return false;
4481 case RISCV::PseudoLHU:
4482 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
4483 return false;
4484 case RISCV::PseudoLW:
4485 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
4486 return false;
4487 case RISCV::PseudoLWU:
4488 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
4489 return false;
4490 case RISCV::PseudoLD:
4491 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
4492 return false;
4493 case RISCV::PseudoLD_RV32:
4494 emitLoadStoreSymbol(Inst, RISCV::LD_RV32, IDLoc, Out, /*HasTmpReg=*/false);
4495 return false;
4496 case RISCV::PseudoFLH:
4497 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
4498 return false;
4499 case RISCV::PseudoFLW:
4500 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
4501 return false;
4502 case RISCV::PseudoFLD:
4503 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
4504 return false;
4505 case RISCV::PseudoFLQ:
4506 emitLoadStoreSymbol(Inst, RISCV::FLQ, IDLoc, Out, /*HasTmpReg=*/true);
4507 return false;
4508 case RISCV::PseudoSB:
4509 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
4510 return false;
4511 case RISCV::PseudoSH:
4512 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
4513 return false;
4514 case RISCV::PseudoSW:
4515 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
4516 return false;
4517 case RISCV::PseudoSD:
4518 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
4519 return false;
4520 case RISCV::PseudoSD_RV32:
4521 emitLoadStoreSymbol(Inst, RISCV::SD_RV32, IDLoc, Out, /*HasTmpReg=*/true);
4522 return false;
4523 case RISCV::PseudoQC_E_LB:
4524 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLB, IDLoc, Out,
4525 /*HasTmpReg=*/false);
4526 return false;
4527 case RISCV::PseudoQC_E_LBU:
4528 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLBU, IDLoc, Out,
4529 /*HasTmpReg=*/false);
4530 return false;
4531 case RISCV::PseudoQC_E_LH:
4532 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLH, IDLoc, Out,
4533 /*HasTmpReg=*/false);
4534 return false;
4535 case RISCV::PseudoQC_E_LHU:
4536 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLHU, IDLoc, Out,
4537 /*HasTmpReg=*/false);
4538 return false;
4539 case RISCV::PseudoQC_E_LW:
4540 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLW, IDLoc, Out,
4541 /*HasTmpReg=*/false);
4542 return false;
4543 case RISCV::PseudoQC_E_SB:
4544 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessSB, IDLoc, Out,
4545 /*HasTmpReg=*/true);
4546 return false;
4547 case RISCV::PseudoQC_E_SH:
4548 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessSH, IDLoc, Out,
4549 /*HasTmpReg=*/true);
4550 return false;
4551 case RISCV::PseudoQC_E_SW:
4552 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessSW, IDLoc, Out,
4553 /*HasTmpReg=*/true);
4554 return false;
4555 case RISCV::PseudoFSH:
4556 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
4557 return false;
4558 case RISCV::PseudoFSW:
4559 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
4560 return false;
4561 case RISCV::PseudoFSD:
4562 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
4563 return false;
4564 case RISCV::PseudoFSQ:
4565 emitLoadStoreSymbol(Inst, RISCV::FSQ, IDLoc, Out, /*HasTmpReg=*/true);
4566 return false;
4567 case RISCV::PseudoAddTPRel:
4568 if (checkPseudoAddTPRel(Inst, Operands))
4569 return true;
4570 break;
4571 case RISCV::PseudoTLSDESCCall:
4572 if (checkPseudoTLSDESCCall(Inst, Operands))
4573 return true;
4574 break;
4575 case RISCV::PseudoSEXT_B:
4576 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
4577 return false;
4578 case RISCV::PseudoSEXT_H:
4579 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
4580 return false;
4581 case RISCV::PseudoZEXT_H:
4582 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
4583 return false;
4584 case RISCV::PseudoZEXT_W:
4585 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
4586 return false;
4587 case RISCV::PseudoVMSGEU_VX_M:
4588 case RISCV::PseudoVMSGEU_VX_M_T:
4589 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
4590 return false;
4591 case RISCV::PseudoVMSGE_VX_M:
4592 case RISCV::PseudoVMSGE_VX_M_T:
4593 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
4594 return false;
4595 case RISCV::PseudoVMSGE_VI:
4596 case RISCV::PseudoVMSLT_VI: {
4597 // These instructions are signed and so is immediate so we can subtract one
4598 // and change the opcode.
4599 int64_t Imm = Inst.getOperand(2).getImm();
4600 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
4601 : RISCV::VMSLE_VI;
4602 emitToStreamer(Out, MCInstBuilder(Opc)
4603 .addOperand(Inst.getOperand(0))
4604 .addOperand(Inst.getOperand(1))
4605 .addImm(Imm - 1)
4606 .addOperand(Inst.getOperand(3))
4607 .setLoc(IDLoc));
4608 return false;
4609 }
4610 case RISCV::PseudoVMSGEU_VI:
4611 case RISCV::PseudoVMSLTU_VI: {
4612 int64_t Imm = Inst.getOperand(2).getImm();
4613 // Unsigned comparisons are tricky because the immediate is signed. If the
4614 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
4615 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
4616 // vmsne v0, v1, v1 which is always false.
4617 if (Imm == 0) {
4618 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4619 ? RISCV::VMSEQ_VV
4620 : RISCV::VMSNE_VV;
4621 emitToStreamer(Out, MCInstBuilder(Opc)
4622 .addOperand(Inst.getOperand(0))
4623 .addOperand(Inst.getOperand(1))
4624 .addOperand(Inst.getOperand(1))
4625 .addOperand(Inst.getOperand(3))
4626 .setLoc(IDLoc));
4627 } else {
4628 // Other immediate values can subtract one like signed.
4629 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4630 ? RISCV::VMSGTU_VI
4631 : RISCV::VMSLEU_VI;
4632 emitToStreamer(Out, MCInstBuilder(Opc)
4633 .addOperand(Inst.getOperand(0))
4634 .addOperand(Inst.getOperand(1))
4635 .addImm(Imm - 1)
4636 .addOperand(Inst.getOperand(3))
4637 .setLoc(IDLoc));
4638 }
4639
4640 return false;
4641 }
4642 case RISCV::PseudoCV_ELW:
4643 emitLoadStoreSymbol(Inst, RISCV::CV_ELW, IDLoc, Out, /*HasTmpReg=*/false);
4644 return false;
4645 }
4646
4647 emitToStreamer(Out, Inst);
4648 return false;
4649}
4650
4651extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
#define Fail
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID)
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool matchRegisterNameHelper(const MCSubtargetInfo &STI, MCRegister &Reg, StringRef Name)
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define RegName(no)
const FeatureInfo AllFeatures[]
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static MCRegister convertGPRToYGPR(MCRegister Reg)
bool isValidInsnFormat(StringRef Format, const MCSubtargetInfo &STI)
static bool isZvvfmmScaleOpcode(unsigned Opcode)
static MCRegister convertFPR64ToFPR128(MCRegister Reg)
static MCRegister convertFPR64ToFPR32(MCRegister Reg)
static cl::opt< bool > AddBuildAttributes("riscv-add-build-attributes", cl::init(false))
static MCRegister convertFPR64ToFPR16(MCRegister Reg)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser()
static MCRegister convertFPR64ToFPR256(MCRegister Reg)
static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg, unsigned Kind)
static unsigned getNFforLXSEG(unsigned Opcode)
unsigned getLMULFromVectorRegister(MCRegister Reg)
static bool isUImm2(const MachineOperand &MO)
SI Fold Operands
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file implements the SmallBitVector class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:31
int64_t getIntVal() const
Definition MCAsmMacro.h:108
bool isNot(TokenKind K) const
Definition MCAsmMacro.h:76
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
StringRef getStringContents() const
Get the contents of a string token (without quotes).
Definition MCAsmMacro.h:83
bool is(TokenKind K) const
Definition MCAsmMacro.h:75
LLVM_ABI SMLoc getEndLoc() const
Definition AsmLexer.cpp:33
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
Encoding
Size and signedness of expression operations' operands.
void printExpr(raw_ostream &, const MCExpr &) const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
MCContext & getContext()
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual bool parseIdentifier(StringRef &Res)=0
Parse an identifier or string (as a quoted identifier) and set Res to the identifier contents.
bool parseOptionalToken(AsmToken::TokenKind T)
Attempt to parse and consume token, returning true on success.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
virtual bool parseAbsoluteExpression(int64_t &Res)=0
Parse an expression which must evaluate to an absolute value.
MCStreamer & getStreamer()
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
const MCObjectFileInfo * getObjectFileInfo() const
Definition MCContext.h:413
LLVM_ABI MCSymbol * createNamedTempSymbol()
Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
Definition MCExpr.cpp:450
ExprKind getKind() const
Definition MCExpr.h:85
unsigned getNumOperands() const
Definition MCInst.h:212
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
ArrayRef< MCOperandInfo > operands() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition MCInstrInfo.h:96
bool isPositionIndependent() const
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual SMLoc getStartLoc() const =0
getStartLoc - Get the location of the first token of this operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual MCRegister getReg() const =0
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
MCRegister getMatchingSuperReg(MCRegister Reg, unsigned SubIdx, const MCRegisterClass *RC) const
Return a super-register of the specified register Reg so its sub-register of index SubIdx is Reg.
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
MCRegister getSubReg(MCRegister Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() const
const FeatureBitset & ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
MCTargetAsmParser - Generic interface to target specific assembly parsers.
const MCSymbol * getAddSym() const
Definition MCValue.h:49
uint32_t getSpecifier() const
Definition MCValue.h:46
const MCSymbol * getSubSym() const
Definition MCValue.h:51
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
static LLVM_ABI bool isSupportedExtensionFeature(StringRef Ext)
static LLVM_ABI std::string getTargetFeatureForExtension(StringRef Ext)
static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true)
Parse RISC-V ISA info from arch string.
static const char * getRegisterName(MCRegister Reg)
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
constexpr const char * getPointer() const
Definition SMLoc.h:33
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
reference emplace_back(ArgTypes &&... Args)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
char back() const
Get the last character in the string.
Definition StringRef.h:153
A switch()-like statement whose cases are string literals.
StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)
#define INT64_MIN
Definition DataTypes.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
uint16_t StackAdjustment(const RuntimeFunction &RF)
StackAdjustment - calculated stack adjustment in words.
Definition ARMWinEH.h:200
LLVM_ABI std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
MCExpr const & getExpr(MCExpr const &Expr)
ABI computeTargetABI(const MCSubtargetInfo &STI, StringRef ABIName)
LLVM_ABI const TagNameMap & getRISCVAttributeTags()
static RoundingMode stringToRoundingMode(StringRef Str)
llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseFeatureBits(const MCSubtargetInfo &STI)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, MCRegister DestReg, SmallVectorImpl< MCInst > &Insts)
bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
LLVM_ABI unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt)
static bool isValidLMUL(unsigned LMUL, bool Fractional)
static bool isValidSEW(unsigned SEW)
LLVM_ABI void printVType(unsigned VType, raw_ostream &OS)
static bool isValidXSfmmVType(unsigned VTypeI)
LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic, bool AltFmt=false)
unsigned encodeRegList(MCRegister EndReg, bool IsRVE=false)
static unsigned getStackAdjBase(unsigned RlistVal, bool IsRV64)
void printRegList(unsigned RlistEncode, raw_ostream &OS)
Specifier parseSpecifierName(StringRef name)
void updateCZceFeatureImplications(MCSubtargetInfo &STI)
uint16_t Specifier
bool isValidYBNDSWImm(int64_t Imm)
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
static SMTVTypeMode stringToSMTVTypeMode(StringRef Str)
static bool isValidSMTVTypeMode(unsigned Mode)
@ Valid
The data is already valid.
initializer< Ty > init(const Ty &Val)
std::function< llvm::json::Value()> Lambda
Definition Mustache.h:84
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1129
@ Length
Definition DWP.cpp:578
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition Error.h:1013
testing::Matcher< const detail::ErrorHolder & > Failed()
Definition Error.h:198
Target & getTheRISCV32Target()
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition MathExtras.h:244
Target & getTheRISCV64beTarget()
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2052
DWARFExpression::Operation Op
Target & getTheRISCV64Target()
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition MathExtras.h:183
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
Definition MathExtras.h:199
Target & getTheRISCV32beTarget()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...