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
9#include "MCTargetDesc/RISCVAsmBackend.h"
10#include "MCTargetDesc/RISCVBaseInfo.h"
11#include "MCTargetDesc/RISCVInstPrinter.h"
12#include "MCTargetDesc/RISCVMCAsmInfo.h"
13#include "MCTargetDesc/RISCVMCTargetDesc.h"
14#include "MCTargetDesc/RISCVMatInt.h"
15#include "MCTargetDesc/RISCVTargetStreamer.h"
16#include "TargetInfo/RISCVTargetInfo.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallBitVector.h"
19#include "llvm/ADT/SmallSet.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/Statistic.h"
22#include "llvm/ADT/StringExtras.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"
27#include "llvm/MC/MCInstBuilder.h"
28#include "llvm/MC/MCInstrInfo.h"
29#include "llvm/MC/MCObjectFileInfo.h"
30#include "llvm/MC/MCParser/AsmLexer.h"
31#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
32#include "llvm/MC/MCParser/MCTargetAsmParser.h"
33#include "llvm/MC/MCRegisterInfo.h"
34#include "llvm/MC/MCStreamer.h"
35#include "llvm/MC/MCSubtargetInfo.h"
36#include "llvm/MC/MCValue.h"
37#include "llvm/MC/TargetRegistry.h"
38#include "llvm/Support/Casting.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/Compiler.h"
41#include "llvm/Support/Debug.h"
42#include "llvm/Support/MathExtras.h"
43#include "llvm/Support/RISCVAttributes.h"
44#include "llvm/TargetParser/RISCVISAInfo.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(Val: 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(Feature: RISCV::Feature64Bit); }
85 bool isRVE() const { return getSTI().hasFeature(Feature: RISCV::FeatureStdExtE); }
86 bool enableExperimentalExtension() const {
87 return getSTI().hasFeature(Feature: 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,
114 OperandVector &Operands);
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);
212 ParseStatus parseFPImm(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(FS: FeatureString);
268
269 // Update the C and Zce implications.
270 RISCV::updateCZceFeatureImplications(STI);
271
272 setAvailableFeatures(ComputeAvailableFeatures(FB: 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(FB: STI.ToggleFeature(FS: 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(Elt: getSTI().getFeatureBits());
288 ParserOptionsStack.push_back(Elt: 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(FB: 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) {
326 MCAsmParserExtension::Initialize(Parser);
327
328 Parser.addAliasForDirective(Directive: ".half", Alias: ".2byte");
329 Parser.addAliasForDirective(Directive: ".hword", Alias: ".2byte");
330 Parser.addAliasForDirective(Directive: ".word", Alias: ".4byte");
331 Parser.addAliasForDirective(Directive: ".dword", Alias: ".8byte");
332 setAvailableFeatures(ComputeAvailableFeatures(FB: STI.getFeatureBits()));
333
334 auto ABIName = StringRef(getTargetOptions().ABIName);
335 if (ABIName.ends_with(Suffix: "f") && !getSTI().hasFeature(Feature: 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(Suffix: "d") &&
340 !getSTI().hasFeature(Feature: 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
353 if (AddBuildAttributes)
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 {
404 XSMTVTypeMode::SMTVTypeMode SMTVType;
405 };
406
407 struct FRMOp {
408 RISCVFPRndMode::RoundingMode FRM;
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(RC: RISCV::GPRRegClassID).contains(Reg: Reg.Reg) ||
500 getRISCVMCRegisterClass(RC: RISCV::FPR64RegClassID).contains(Reg: Reg.Reg) ||
501 getRISCVMCRegisterClass(RC: RISCV::VRRegClassID).contains(Reg: Reg.Reg));
502 }
503 bool isAnyRegC() const {
504 return Kind == KindTy::Register &&
505 (getRISCVMCRegisterClass(RC: RISCV::GPRCRegClassID).contains(Reg: Reg.Reg) ||
506 getRISCVMCRegisterClass(RC: RISCV::FPR64CRegClassID).contains(Reg: 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(RC: RISCV::GPRRegClassID).contains(Reg: Reg.Reg);
521 }
522
523 bool isYGPR() const {
524 return Kind == KindTy::Register &&
525 getRISCVMCRegisterClass(RC: RISCV::YGPRRegClassID).contains(Reg: Reg.Reg);
526 }
527
528 bool isGPRPair() const {
529 return Kind == KindTy::Register &&
530 getRISCVMCRegisterClass(RC: RISCV::GPRPairRegClassID).contains(Reg: Reg.Reg);
531 }
532
533 bool isGPRPairC() const {
534 return Kind == KindTy::Register &&
535 getRISCVMCRegisterClass(RC: RISCV::GPRPairCRegClassID).contains(Reg: Reg.Reg);
536 }
537
538 bool isGPRPairNoX0() const {
539 return Kind == KindTy::Register &&
540 getRISCVMCRegisterClass(RC: RISCV::GPRPairNoX0RegClassID)
541 .contains(Reg: Reg.Reg);
542 }
543
544 bool isGPRF16() const {
545 return Kind == KindTy::Register &&
546 getRISCVMCRegisterClass(RC: RISCV::GPRF16RegClassID).contains(Reg: Reg.Reg);
547 }
548
549 bool isGPRF32() const {
550 return Kind == KindTy::Register &&
551 getRISCVMCRegisterClass(RC: RISCV::GPRF32RegClassID).contains(Reg: 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>(Val: 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(Expr: getExpr(), Imm))
576 return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
577
578 RISCV::Specifier VK = RISCV::S_None;
579 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
591 return isInt<N>(fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
592
593 RISCV::Specifier VK = RISCV::S_None;
594 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
604 return false;
605
606 RISCV::Specifier VK = RISCV::S_None;
607 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
615 return false;
616
617 RISCV::Specifier VK = RISCV::S_None;
618 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
626 return false;
627
628 RISCV::Specifier VK = RISCV::S_None;
629 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
637 return false;
638
639 RISCV::Specifier VK = RISCV::S_None;
640 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
648 return false;
649
650 RISCV::Specifier VK = RISCV::S_None;
651 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
659 return false;
660
661 RISCV::Specifier VK = RISCV::S_None;
662 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(VTypeI: VType.Val);
683 }
684
685 bool isTileLambda() const {
686 return isUImmPred(p: [](int64_t Imm) { return Imm && isUInt<3>(x: 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(Mode: 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;
715 int Idx = RISCVLoadFPImm::getLoadFPImm(
716 FPImm: 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(Expr: getExpr(), Imm))
729 return isRV64Expr() || (isInt<32>(x: Imm) || isUInt<32>(x: Imm));
730
731 return RISCVAsmParser::isSymbolDiff(Expr: getExpr());
732 }
733
734 bool isImmXLenLI_Restricted() const {
735 int64_t Imm;
736 if (!isExpr())
737 return false;
738 bool IsConstantImm = evaluateConstantExpr(Expr: getExpr(), Imm);
739 // 'la imm' supports constant immediates only.
740 return IsConstantImm &&
741 (isRV64Expr() || (isInt<32>(x: Imm) || isUInt<32>(x: Imm)));
742 }
743
744 template <unsigned N> bool isUImm() const {
745 int64_t Imm;
746 if (!isExpr())
747 return false;
748 bool IsConstantImm = evaluateConstantExpr(Expr: 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(Expr: 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(Expr: 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(p: [](int64_t Imm) { return Imm != 0 && isUInt<6>(x: Imm); });
777 return isUImmPred(p: [](int64_t Imm) { return Imm != 0 && isUInt<5>(x: 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(p: [](int64_t Imm) { return Imm != 0 && isUInt<5>(x: Imm); });
805 }
806
807 bool isUImm5GT3() const {
808 return isUImmPred(p: [](int64_t Imm) { return isUInt<5>(x: Imm) && Imm > 3; });
809 }
810
811 bool isUImm4Plus1() const {
812 return isUImmPred(
813 p: [](int64_t Imm) { return Imm > 0 && isUInt<4>(x: Imm - 1); });
814 }
815
816 bool isUImm5Plus1() const {
817 return isUImmPred(
818 p: [](int64_t Imm) { return Imm > 0 && isUInt<5>(x: Imm - 1); });
819 }
820
821 bool isUImm6Plus1() const {
822 return isUImmPred(
823 p: [](int64_t Imm) { return Imm > 0 && isUInt<6>(x: Imm - 1); });
824 }
825
826 bool isUImm5GE6Plus1() const {
827 return isUImmPred(
828 p: [](int64_t Imm) { return Imm >= 6 && isUInt<5>(x: Imm - 1); });
829 }
830
831 bool isUImm5Slist() const {
832 return isUImmPred(p: [](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 p: [this](int64_t Imm) { return isRV64Expr() ? Imm == 64 : Imm == 32; });
841 }
842
843 bool isUImm8GE32() const {
844 return isUImmPred(p: [](int64_t Imm) { return isUInt<8>(x: Imm) && Imm >= 32; });
845 }
846
847 bool isRnumArg() const {
848 return isUImmPred(
849 p: [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(10); });
850 }
851
852 bool isRnumArg_0_7() const {
853 return isUImmPred(
854 p: [](int64_t Imm) { return Imm >= INT64_C(0) && Imm <= INT64_C(7); });
855 }
856
857 bool isRnumArg_1_10() const {
858 return isUImmPred(
859 p: [](int64_t Imm) { return Imm >= INT64_C(1) && Imm <= INT64_C(10); });
860 }
861
862 bool isRnumArg_2_14() const {
863 return isUImmPred(
864 p: [](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(Expr: getExpr(), Imm);
872 return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
873 }
874
875 bool isYBNDSWImm() const {
876 if (!isExpr())
877 return false;
878
879 int64_t Imm;
880 bool IsConstantImm = evaluateConstantExpr(Expr: 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(Expr: getExpr(), Imm);
889 return IsConstantImm && p(fixImmediateForRV32(Imm, IsRV64Imm: 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(p: [](int64_t Imm) { return Imm != 0 && isInt<5>(x: Imm); });
902 }
903
904 bool isSImm6NonZero() const {
905 return isSImmPred(p: [](int64_t Imm) { return Imm != 0 && isInt<6>(x: Imm); });
906 }
907
908 bool isCLUIImm() const {
909 return isUImmPred(p: [](int64_t Imm) {
910 return (isUInt<5>(x: 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 p: [](int64_t Imm) { return isShiftedUInt<8, 2>(x: 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>(x: Imm))
943 return Imm;
944 return SignExtend64<32>(x: Imm);
945 }
946
947 bool isSImm12LO() const {
948 if (!isExpr())
949 return false;
950
951 int64_t Imm;
952 if (evaluateConstantExpr(Expr: getExpr(), Imm))
953 return isInt<12>(x: fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
954
955 RISCV::Specifier VK = RISCV::S_None;
956 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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())
970 return DiagnosticPredicate::NoMatch;
971 return (this->*Pred)() ? DiagnosticPredicate::Match
972 : DiagnosticPredicate::NearMatch;
973 }
974
975 bool isSImm12Lsb00000() const {
976 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<7, 5>(x: Imm); });
977 }
978
979 bool isSImm10Lsb0000NonZero() const {
980 return isSImmPred(
981 p: [](int64_t Imm) { return Imm != 0 && isShiftedInt<6, 4>(x: Imm); });
982 }
983
984 bool isSImm16NonZero() const {
985 return isSImmPred(p: [](int64_t Imm) { return Imm != 0 && isInt<16>(x: Imm); });
986 }
987
988 bool isUImm16NonZero() const {
989 return isUImmPred(p: [](int64_t Imm) { return isUInt<16>(x: Imm) && Imm != 0; });
990 }
991
992 bool isSImm20LI() const {
993 if (!isExpr())
994 return false;
995
996 int64_t Imm;
997 if (evaluateConstantExpr(Expr: getExpr(), Imm))
998 return isInt<20>(x: fixImmediateForRV32(Imm, IsRV64Imm: isRV64Expr()));
999
1000 RISCV::Specifier VK = RISCV::S_None;
1001 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(p: [](int64_t Imm) {
1010 return isUInt<16>(x: Imm) && isInt<10>(x: SignExtend64<16>(x: Imm));
1011 });
1012 }
1013 bool isSImm10PLI_W() const {
1014 return isSImm<10>() || isUImmPred(p: [](int64_t Imm) {
1015 return isUInt<32>(x: Imm) && isInt<10>(x: SignExtend64<32>(x: Imm));
1016 });
1017 }
1018
1019 bool isUImm20LUI() const {
1020 if (!isExpr())
1021 return false;
1022
1023 int64_t Imm;
1024 if (evaluateConstantExpr(Expr: getExpr(), Imm))
1025 return isUInt<20>(x: Imm);
1026
1027 RISCV::Specifier VK = RISCV::S_None;
1028 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(Expr: getExpr(), Imm))
1038 return isUInt<20>(x: Imm);
1039
1040 RISCV::Specifier VK = RISCV::S_None;
1041 return RISCVAsmParser::classifySymbolRef(Expr: getExpr(), Kind&: 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(p: [](int64_t Imm) { return 0 == Imm; });
1049 }
1050
1051 bool isImmThree() const {
1052 return isUImmPred(p: [](int64_t Imm) { return 3 == Imm; });
1053 }
1054
1055 bool isImmFour() const {
1056 return isUImmPred(p: [](int64_t Imm) { return 4 == Imm; });
1057 }
1058
1059 bool isImm5Zibi() const {
1060 return isUImmPred(
1061 p: [](int64_t Imm) { return (Imm != 0 && isUInt<5>(x: Imm)) || Imm == -1; });
1062 }
1063
1064 bool isSImm5Plus1() const {
1065 return isSImmPred(
1066 p: [](int64_t Imm) { return Imm != INT64_MIN && isInt<5>(x: Imm - 1); });
1067 }
1068
1069 bool isSImm18() const {
1070 return isSImmPred(p: [](int64_t Imm) { return isInt<18>(x: Imm); });
1071 }
1072
1073 bool isSImm18Lsb0() const {
1074 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<17, 1>(x: Imm); });
1075 }
1076
1077 bool isSImm19Lsb00() const {
1078 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<17, 2>(x: Imm); });
1079 }
1080
1081 bool isSImm20Lsb000() const {
1082 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<17, 3>(x: Imm); });
1083 }
1084
1085 bool isSImm32Lsb0() const {
1086 return isSImmPred(p: [](int64_t Imm) { return isShiftedInt<31, 1>(x: 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)
1148 return RISCVInstPrinter::getRegisterName(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(VType: getVType(), OS);
1175 OS << '>';
1176 break;
1177 case KindTy::FRM:
1178 OS << "<frm: ";
1179 OS << roundingModeToString(RndMode: getFRM());
1180 OS << '>';
1181 break;
1182 case KindTy::SMTVType:
1183 OS << "<smtvtype: ";
1184 OS << SMTVTypeModeToString(TypeMode: 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(RlistEncode: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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>(args: 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 Op: MCOperand::createImm(Val: fixImmediateForRV32(Imm, IsRV64Imm)));
1323 else
1324 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
1325 }
1326
1327 // Used by the TableGen Code
1328 void addRegOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
1330 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
1331 }
1332
1333 void addImmOperands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
1335 addExpr(Inst, Expr: getExpr(), IsRV64Imm: 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(Expr: getExpr(), Imm);
1343 assert(IsConstant);
1344 Inst.addOperand(Op: MCOperand::createImm(Val: SignExtend64<Bits>(Imm)));
1345 }
1346
1347 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1348 assert(N == 1 && "Invalid number of operands!");
1349 if (isExpr()) {
1350 addExpr(Inst, Expr: getExpr(), IsRV64Imm: isRV64Expr());
1351 return;
1352 }
1353
1354 int Imm = RISCVLoadFPImm::getLoadFPImm(
1355 FPImm: APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1356 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
1357 }
1358
1359 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
1360 assert(N == 1 && "Invalid number of operands!");
1361 Inst.addOperand(Op: MCOperand::createImm(Val: Fence.Val));
1362 }
1363
1364 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
1366 Inst.addOperand(Op: MCOperand::createImm(Val: 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(Expr: getExpr(), Imm);
1378 assert(IsConstantImm && "Invalid VTypeI Operand!");
1379 } else {
1380 Imm = getVType();
1381 }
1382 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
1383 }
1384
1385 void addRegListOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 Inst.addOperand(Op: MCOperand::createImm(Val: RegList.Encoding));
1388 }
1389
1390 void addRegRegOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 2 && "Invalid number of operands!");
1392 Inst.addOperand(Op: MCOperand::createReg(Reg: RegReg.BaseReg));
1393 Inst.addOperand(Op: MCOperand::createReg(Reg: RegReg.OffsetReg));
1394 }
1395
1396 void addStackAdjOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 Inst.addOperand(Op: MCOperand::createImm(Val: StackAdj.Val));
1399 }
1400
1401 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 Inst.addOperand(Op: MCOperand::createImm(Val: getFRM()));
1404 }
1405
1406 void addSMTVTypeOperand(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
1408 Inst.addOperand(Op: MCOperand::createImm(Val: 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
1419static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
1420 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1421 return Reg - RISCV::F0_D + RISCV::F0_H;
1422}
1423
1424static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
1425 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1426 return Reg - RISCV::F0_D + RISCV::F0_F;
1427}
1428
1429static MCRegister convertFPR64ToFPR128(MCRegister Reg) {
1430 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1431 return Reg - RISCV::F0_D + RISCV::F0_Q;
1432}
1433
1434static MCRegister convertGPRToYGPR(MCRegister Reg) {
1435 assert(Reg >= RISCV::X0 && Reg <= RISCV::X31 && "Invalid register");
1436 return Reg - RISCV::X0 + RISCV::X0_Y;
1437}
1438
1439static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
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, SubIdx: RISCV::sub_vrm1_0,
1451 RC: &getRISCVMCRegisterClass(RC: RegClassID));
1452}
1453
1454static MCRegister convertFPR64ToFPR256(MCRegister Reg) {
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(RC: RISCV::FPR64RegClassID).contains(Reg);
1468 bool IsRegFPR64C =
1469 getRISCVMCRegisterClass(RC: RISCV::FPR64CRegClassID).contains(Reg);
1470 bool IsRegVR = getRISCVMCRegisterClass(RC: 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(RC: RISCV::GPRRegClassID).contains(Reg) &&
1512 Kind == MCK_GPRF64AsFPR && STI->hasFeature(Feature: 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(RI: *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(L: ErrorLoc, Msg: 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(MatchResult: (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,
1767 OperandVector &Operands) {
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()) {
1777 case NearMissInfo::NearMissOperand: {
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(Args: NearMissMessage{
1787 .Loc: OperandLoc, .Message: "unexpected extra operand for instruction"});
1788 ReportedTooManyOperands = true;
1789 }
1790 break;
1791 }
1792
1793 std::string OperandDiag = getCustomOperandDiag(MatchError: 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(x: I.getOperandIndex());
1800 if (std::any_of(
1801 first: PrevReports.first, last: PrevReports.second,
1802 pred: [DupCheckMatchClass](const std::pair<unsigned, unsigned> Pair) {
1803 if (DupCheckMatchClass == ~0U || Pair.second == ~0U)
1804 return Pair.second == DupCheckMatchClass;
1805 return isSubclass(A: (MatchClassKind)DupCheckMatchClass,
1806 B: (MatchClassKind)Pair.second);
1807 }))
1808 break;
1809 OperandMissesSeen.insert(
1810 x: std::make_pair(x: I.getOperandIndex(), y&: 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(Args&: Message);
1825 break;
1826 }
1827 case NearMissInfo::NearMissFeature: {
1828 const FeatureBitset &MissingFeatures = I.getFeatures();
1829 // Don't report the same set of features twice.
1830 if (!FeatureMissesSeen.insert(V: 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(Val: Feature);
1840 FirstFeature = false;
1841 }
1842 NearMissesOut.emplace_back(Args&: Message);
1843 break;
1844 }
1845 case NearMissInfo::NearMissPredicate:
1846 // RISC-V does not define any target match predicates.
1847 llvm_unreachable("RISC-V has no target predicate near-misses");
1848 break;
1849 case NearMissInfo::NearMissTooFewOperands: {
1850 if (!ReportedTooFewOperands) {
1851 SMLoc EndLoc = ((RISCVOperand &)*Operands.back()).getEndLoc();
1852 NearMissesOut.emplace_back(
1853 Args: NearMissMessage{.Loc: EndLoc, .Message: "too few operands for instruction"});
1854 ReportedTooFewOperands = true;
1855 }
1856 break;
1857 }
1858 case NearMissInfo::NoNearMiss:
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) {
1868 SmallVector<NearMissMessage, 4> Messages;
1869 FilterNearMisses(NearMissesIn&: NearMisses, NearMissesOut&: 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(L: IDLoc, Msg: "invalid instruction");
1875 } else if (Messages.size() == 1) {
1876 // One near miss was found, report it as the sole error.
1877 Error(L: Messages[0].Loc, Msg: 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(L: IDLoc,
1882 Msg: "invalid instruction, any one of the following would fix this:");
1883 for (auto &M : Messages)
1884 Note(L: M.Loc, Msg: M.Message);
1885 }
1886}
1887
1888bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1889 OperandVector &Operands,
1890 MCStreamer &Out,
1891 uint64_t &ErrorInfo,
1892 bool MatchingInlineAsm) {
1893 MCInst Inst;
1894 SmallVector<NearMissInfo, 4> NearMisses;
1895
1896 auto Result =
1897 MatchInstructionImpl(Operands, Inst, NearMisses: &NearMisses, matchingInlineAsm: 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(FB: getSTI().getFeatureBits());
1907 std::string Suggestion = RISCVMnemonicSpellCheck(
1908 S: ((RISCVOperand &)*Operands[0]).getToken(), FBS, VariantID: 0);
1909 return Error(L: IDLoc, Msg: "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(L: StartLoc, Msg: "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
1956 Reg = matchRegisterNameHelper(Name);
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(K: 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(Token: LParen);
1986 return ParseStatus::NoMatch;
1987 case AsmToken::Identifier:
1988 StringRef Name = getLexer().getTok().getIdentifier();
1989 MCRegister Reg = matchRegisterNameHelper(Name);
1990
1991 if (!Reg) {
1992 if (HadParens)
1993 getLexer().UnLex(Token: LParen);
1994 return ParseStatus::NoMatch;
1995 }
1996 if (HadParens)
1997 Operands.push_back(Elt: RISCVOperand::createToken(Str: "(", S: FirstS));
1998 SMLoc S = getLoc();
1999 SMLoc E = getTok().getEndLoc();
2000 getLexer().Lex();
2001 Operands.push_back(Elt: RISCVOperand::createReg(Reg, S, E));
2002 }
2003
2004 if (HadParens) {
2005 getParser().Lex(); // Eat ')'
2006 Operands.push_back(Elt: RISCVOperand::createToken(Str: ")", S: 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, EndLoc&: E))
2028 return ParseStatus::Failure;
2029
2030 auto *CE = dyn_cast<MCConstantExpr>(Val: Res);
2031 if (CE) {
2032 int64_t Imm = CE->getValue();
2033 if (isUInt<7>(x: Imm)) {
2034 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2035 return ParseStatus::Success;
2036 }
2037 }
2038
2039 break;
2040 }
2041 case AsmToken::Identifier: {
2042 StringRef Identifier;
2043 if (getParser().parseIdentifier(Res&: Identifier))
2044 return ParseStatus::Failure;
2045
2046 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Name: Identifier);
2047 if (Opcode) {
2048 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
2049 "Unexpected opcode");
2050 Res = MCConstantExpr::create(Value: Opcode->Value, Ctx&: getContext());
2051 E = SMLoc::getFromPointer(Ptr: S.getPointer() + Identifier.size());
2052 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2053 return ParseStatus::Success;
2054 }
2055
2056 break;
2057 }
2058 case AsmToken::Percent:
2059 break;
2060 }
2061
2062 return generateImmOutOfRangeError(
2063 ErrorLoc: S, Lower: 0, Upper: 127,
2064 Msg: "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, EndLoc&: E))
2083 return ParseStatus::Failure;
2084
2085 auto *CE = dyn_cast<MCConstantExpr>(Val: Res);
2086 if (CE) {
2087 int64_t Imm = CE->getValue();
2088 if (Imm >= 0 && Imm <= 2) {
2089 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2090 return ParseStatus::Success;
2091 }
2092 }
2093
2094 break;
2095 }
2096 case AsmToken::Identifier: {
2097 StringRef Identifier;
2098 if (getParser().parseIdentifier(Res&: 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(Value: Opcode, Ctx&: getContext());
2112 E = SMLoc::getFromPointer(Ptr: S.getPointer() + Identifier.size());
2113 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2114 return ParseStatus::Success;
2115 }
2116 case AsmToken::Percent: {
2117 // Discard operand with modifier.
2118 break;
2119 }
2120 }
2121
2122 return generateImmOutOfRangeError(
2123 ErrorLoc: S, Lower: 0, Upper: 2,
2124 Msg: "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>(Val: E)) {
2133 int64_t Imm = CE->getValue();
2134 if (isUInt<12>(x: Imm)) {
2135 auto Range = RISCVSysReg::lookupSysRegByEncoding(Encoding: 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(ActiveFeatures: STI->getFeatureBits()))
2142 return RISCVOperand::createSysReg(
2143 Str: RISCVSysReg::getSysRegStr(Reg.Name), S, Encoding: 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(Str: "", S, Encoding: 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(Elt: std::move(SysOpnd));
2168 return ParseStatus::Success;
2169 }
2170
2171 return generateImmOutOfRangeError(ErrorLoc: S, Lower: 0, Upper: (1 << 12) - 1);
2172 }
2173 case AsmToken::Identifier: {
2174 StringRef Identifier;
2175 if (getParser().parseIdentifier(Res&: Identifier))
2176 return ParseStatus::Failure;
2177
2178 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Name: Identifier);
2179
2180 if (SysReg) {
2181 if (SysReg->IsDeprecatedName) {
2182 // Lookup the undeprecated name.
2183 auto Range = RISCVSysReg::lookupSysRegByEncoding(Encoding: SysReg->Encoding);
2184 for (auto &Reg : Range) {
2185 if (Reg.IsAltName || Reg.IsDeprecatedName)
2186 continue;
2187 Warning(L: S, Msg: "'" + 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(ActiveFeatures: FeatureBits)) {
2196 const auto *Feature =
2197 llvm::find_if(Range: AllFeatures, P: [&](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(cont: AllFeatures))
2206 ErrorMsg += " and ";
2207 }
2208 if (Feature != std::end(cont: AllFeatures)) {
2209 ErrorMsg +=
2210 "requires '" + std::string(Feature->key()) + "' to be enabled";
2211 }
2212
2213 return Error(L: S, Msg: ErrorMsg);
2214 }
2215 Operands.push_back(
2216 Elt: RISCVOperand::createSysReg(Str: Identifier, S, Encoding: SysReg->Encoding));
2217 return ParseStatus::Success;
2218 }
2219
2220 // Accept a symbol name that evaluates to an absolute value.
2221 MCSymbol *Sym = getContext().lookupSymbol(Name: 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(Elt: std::move(SysOpnd));
2227 return ParseStatus::Success;
2228 }
2229 }
2230
2231 return generateImmOutOfRangeError(ErrorLoc: S, Lower: 0, Upper: (1 << 12) - 1,
2232 Msg: "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(ErrorLoc: S, Lower: 0, Upper: (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(K: AsmToken::Identifier)) {
2249 StringRef Identifier = getTok().getIdentifier();
2250 if (Identifier.compare_insensitive(RHS: "inf") == 0) {
2251 Operands.push_back(
2252 Elt: RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: 30, Ctx&: getContext()), S,
2253 E: getTok().getEndLoc(), IsRV64: isRV64()));
2254 } else if (Identifier.compare_insensitive(RHS: "nan") == 0) {
2255 Operands.push_back(
2256 Elt: RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: 31, Ctx&: getContext()), S,
2257 E: getTok().getEndLoc(), IsRV64: isRV64()));
2258 } else if (Identifier.compare_insensitive(RHS: "min") == 0) {
2259 Operands.push_back(
2260 Elt: RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: 1, Ctx&: getContext()), S,
2261 E: getTok().getEndLoc(), IsRV64: isRV64()));
2262 } else {
2263 return TokError(Msg: "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(T: AsmToken::Minus);
2273
2274 const AsmToken &Tok = getTok();
2275 if (!Tok.is(K: AsmToken::Real))
2276 return TokError(Msg: "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(Err: StatusOrErr.takeError()))
2283 return TokError(Msg: "invalid floating point representation");
2284
2285 if (IsNegative)
2286 RealVal.changeSign();
2287
2288 Operands.push_back(Elt: RISCVOperand::createFPImm(
2289 Val: 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:
2312 case AsmToken::Identifier:
2313 if (getParser().parseExpression(Res, EndLoc&: E))
2314 return ParseStatus::Failure;
2315 break;
2316 case AsmToken::Percent:
2317 return parseOperandWithSpecifier(Operands);
2318 }
2319
2320 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: isRV64()));
2321 return ParseStatus::Success;
2322}
2323
2324ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
2325 SMLoc S = getLoc();
2326 SMLoc E;
2327
2328 if (parseToken(T: AsmToken::Percent, Msg: "expected '%' relocation specifier"))
2329 return ParseStatus::Failure;
2330 const MCExpr *Expr = nullptr;
2331 bool Failed = parseExprWithSpecifier(Res&: Expr, E);
2332 if (!Failed)
2333 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Expr, S, E, IsRV64: 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(Msg: "expected '%' relocation specifier");
2341 StringRef Identifier = getParser().getTok().getIdentifier();
2342 auto Spec = RISCV::parseSpecifierName(name: Identifier);
2343 if (!Spec)
2344 return TokError(Msg: "invalid relocation specifier");
2345
2346 getParser().Lex(); // Eat the identifier
2347 if (parseToken(T: AsmToken::LParen, Msg: "expected '('"))
2348 return true;
2349
2350 const MCExpr *SubExpr;
2351 if (getParser().parseParenExpression(Res&: SubExpr, EndLoc&: E))
2352 return true;
2353
2354 Res = MCSpecifierExpr::create(Expr: SubExpr, S: Spec, Ctx&: getContext(), Loc);
2355 return false;
2356}
2357
2358bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {
2359 SMLoc E;
2360 if (parseOptionalToken(T: 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(Name: Identifier);
2374
2375 if (Sym->isVariable()) {
2376 const MCExpr *V = Sym->getVariableValue();
2377 if (!isa<MCSymbolRefExpr>(Val: V))
2378 return ParseStatus::NoMatch;
2379 }
2380
2381 SMLoc E;
2382 if (getParser().parseExpression(Res, EndLoc&: E))
2383 return ParseStatus::Failure;
2384
2385 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: 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(K: AsmToken::At)) {
2398 Lex();
2399 Lex();
2400 StringRef PLT;
2401 SMLoc Loc = getLoc();
2402 if (getParser().parseIdentifier(Res&: PLT) || PLT != "plt")
2403 return Error(L: Loc, Msg: "@ (except the deprecated/ignored @plt) is disallowed");
2404 } else if (!getLexer().peekTok().is(K: 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(Ptr: S.getPointer() + Identifier.size());
2412 RISCV::Specifier Kind = RISCV::S_CALL_PLT;
2413
2414 MCSymbol *Sym = getContext().getOrCreateSymbol(Name: Identifier);
2415 Res = MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext());
2416 Res = MCSpecifierExpr::create(Expr: Res, S: Kind, Ctx&: getContext());
2417 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: 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, EndLoc&: E))
2427 return ParseStatus::Failure;
2428
2429 if (Res->getKind() != MCExpr::ExprKind::SymbolRef)
2430 return Error(L: S, Msg: "operand must be a valid jump target");
2431
2432 Res = MCSpecifierExpr::create(Expr: Res, S: RISCV::S_CALL_PLT, Ctx&: getContext());
2433 Operands.push_back(Elt: RISCVOperand::createExpr(Val: Res, S, E, IsRV64: 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(K: AsmToken::Identifier) &&
2448 getLexer().peekTok().is(K: 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(K: AsmToken::Identifier))
2459 return true;
2460
2461 StringRef Identifier = Tok.getIdentifier();
2462 if (State < VTypeState::SeenSew && Identifier.consume_front(Prefix: "e")) {
2463 if (Identifier.getAsInteger(Radix: 10, Result&: 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: Sew))
2475 return true;
2476
2477 State = VTypeState::SeenSew;
2478 return false;
2479 }
2480
2481 if (State < VTypeState::SeenLmul && Identifier.consume_front(Prefix: "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(Prefix: "f");
2491 if (Identifier.getAsInteger(Radix: 10, Result&: Lmul))
2492 return true;
2493 if (!RISCVVType::isValidLMUL(LMUL: Lmul, Fractional))
2494 return true;
2495
2496 if (Fractional) {
2497 unsigned ELEN = STI->hasFeature(Feature: RISCV::FeatureStdExtZve64x) ? 64 : 32;
2498 unsigned MinLMUL = ELEN / 8;
2499 if (Lmul > MinLMUL)
2500 Warning(L: Tok.getLoc(),
2501 Msg: "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(Prefix: "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(Prefix: "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(Tok: 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(T: AsmToken::Comma));
2559
2560 if (!getLexer().is(K: AsmToken::EndOfStatement) ||
2561 State == VTypeState::SeenNothingYet)
2562 return generateVTypeError(ErrorLoc: S);
2563
2564 RISCVVType::VLMUL VLMUL = RISCVVType::encodeLMUL(LMUL: Lmul, Fractional);
2565 if (Fractional) {
2566 unsigned ELEN = STI->hasFeature(Feature: 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(L: S, Msg: "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: Sew, TailAgnostic, MaskAgnostic, AltFmt);
2577 Operands.push_back(Elt: RISCVOperand::createVType(VTypeI, S));
2578 return ParseStatus::Success;
2579}
2580
2581bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2582 return Error(L: ErrorLoc,
2583 Msg: "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(K: AsmToken::Identifier))
2596 goto Fail;
2597
2598 Identifier = getTok().getIdentifier();
2599
2600 if (!Identifier.consume_front(Prefix: "e"))
2601 goto Fail;
2602
2603 if (Identifier.getAsInteger(Radix: 10, Result&: 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(T: AsmToken::Comma))
2616 goto Fail;
2617
2618 if (getTok().isNot(K: AsmToken::Identifier))
2619 goto Fail;
2620
2621 Identifier = getTok().getIdentifier();
2622
2623 if (!Identifier.consume_front(Prefix: "w"))
2624 goto Fail;
2625 if (Identifier.getAsInteger(Radix: 10, Result&: Widen))
2626 goto Fail;
2627 if (Widen != 1 && Widen != 2 && Widen != 4)
2628 goto Fail;
2629
2630 Lex();
2631
2632 if (getLexer().is(K: AsmToken::EndOfStatement)) {
2633 Operands.push_back(Elt: RISCVOperand::createVType(
2634 VTypeI: RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
2635 return ParseStatus::Success;
2636 }
2637
2638Fail:
2639 return generateXSfmmVTypeError(ErrorLoc: S);
2640}
2641
2642bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
2643 return Error(L: ErrorLoc, Msg: "operand must be e[8|16|16alt|32|64],w[1|2|4]");
2644}
2645
2646ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2647 if (getLexer().isNot(K: AsmToken::Identifier))
2648 return ParseStatus::NoMatch;
2649
2650 StringRef Name = getLexer().getTok().getIdentifier();
2651 if (!Name.consume_back(Suffix: ".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(L: getLoc(), Msg: "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(Elt: RISCVOperand::createReg(Reg, S, E));
2668 return ParseStatus::Success;
2669}
2670
2671ParseStatus RISCVAsmParser::parseVScaleReg(OperandVector &Operands) {
2672 if (getLexer().isNot(K: AsmToken::Identifier))
2673 return ParseStatus::NoMatch;
2674
2675 StringRef Name = getLexer().getTok().getIdentifier();
2676 if (!Name.consume_back(Suffix: ".scale"))
2677 return Error(L: getLoc(), Msg: "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(Elt: RISCVOperand::createReg(Reg, S, E));
2688 return ParseStatus::Success;
2689}
2690
2691ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
2692 if (getLexer().isNot(K: AsmToken::Identifier))
2693 return ParseStatus::NoMatch;
2694
2695 SMLoc S = getLoc();
2696 StringRef Name = getLexer().getTok().getIdentifier();
2697 if (!Name.consume_front(Prefix: "L") && !Name.consume_front(Prefix: "l"))
2698 return ParseStatus::NoMatch;
2699
2700 unsigned Lambda;
2701 if (Name.getAsInteger(Radix: 10, Result&: Lambda) || !isPowerOf2_32(Value: Lambda) || Lambda >= 128)
2702 return Error(L: S, Msg: "operand must be L1, L2, L4, L8, L16, L32, or L64");
2703
2704 unsigned EncodedLambda = Log2_32(Value: Lambda) + 1;
2705
2706 SMLoc E = getTok().getEndLoc();
2707 getLexer().Lex();
2708 Operands.push_back(Elt: RISCVOperand::createExpr(
2709 Val: MCConstantExpr::create(Value: EncodedLambda, Ctx&: getContext()), S, E, IsRV64: isRV64()));
2710 return ParseStatus::Success;
2711}
2712
2713ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
2714 if (!isRV64() || getSTI().hasFeature(Feature: RISCV::FeatureStdExtF))
2715 return ParseStatus::NoMatch;
2716
2717 return parseGPRAsFPR(Operands);
2718}
2719
2720ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2721 if (getLexer().isNot(K: 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(Elt: RISCVOperand::createReg(
2733 Reg, S, E, IsGPRAsFPR: !getSTI().hasFeature(Feature: RISCV::FeatureStdExtF)));
2734 return ParseStatus::Success;
2735}
2736
2737ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
2738 if (isRV64() || getSTI().hasFeature(Feature: RISCV::FeatureStdExtF))
2739 return ParseStatus::NoMatch;
2740
2741 if (getLexer().isNot(K: 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(RC: 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(Feature: RISCV::FeatureStdExtZfinx))
2757 return TokError(Msg: "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, SubIdx: RISCV::sub_gpr_even,
2769 RC: &getRISCVMCRegisterClass(RC: RISCV::GPRPairRegClassID));
2770 Operands.push_back(Elt: RISCVOperand::createReg(Reg: Pair, S, E, /*isGPRAsFPR=*/IsGPRAsFPR: true));
2771 return ParseStatus::Success;
2772}
2773
2774template <bool IsRV64>
2775ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2776 return parseGPRPair(Operands, IsRV64Inst: 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(K: 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(RC: RISCV::GPRRegClassID).contains(Reg))
2799 return ParseStatus::NoMatch;
2800
2801 if ((Reg - RISCV::X0) & 1)
2802 return TokError(Msg: "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, SubIdx: RISCV::sub_gpr_even,
2811 RC: &getRISCVMCRegisterClass(RC: RISCV::GPRPairRegClassID));
2812 Operands.push_back(Elt: RISCVOperand::createReg(Reg: Pair, S, E));
2813 return ParseStatus::Success;
2814}
2815
2816ParseStatus RISCVAsmParser::parseSMTVType(OperandVector &Operands) {
2817 if (getLexer().isNot(K: AsmToken::Identifier))
2818 return TokError(
2819 Msg: "operand must be a valid SpacemiT's Integer Matrix VType mnemonic");
2820
2821 StringRef Str = getLexer().getTok().getIdentifier();
2822 XSMTVTypeMode::SMTVTypeMode VType = XSMTVTypeMode::stringToSMTVTypeMode(Str);
2823
2824 if (!isValidSMTVTypeMode(Mode: VType))
2825 return TokError(Msg: "SpacemiT's Integer Matrix only supports [i4|i8] mode");
2826
2827 Operands.push_back(Elt: RISCVOperand::createSMTVType(VType, S: getLoc()));
2828 Lex(); // Eat identifier token.
2829 return ParseStatus::Success;
2830}
2831
2832ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2833 if (getLexer().isNot(K: AsmToken::Identifier))
2834 return TokError(
2835 Msg: "operand must be a valid floating point rounding mode mnemonic");
2836
2837 StringRef Str = getLexer().getTok().getIdentifier();
2838 RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);
2839
2840 if (FRM == RISCVFPRndMode::Invalid)
2841 return TokError(
2842 Msg: "operand must be a valid floating point rounding mode mnemonic");
2843
2844 Operands.push_back(Elt: RISCVOperand::createFRMArg(FRM, S: getLoc()));
2845 Lex(); // Eat identifier token.
2846 return ParseStatus::Success;
2847}
2848
2849std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultSMTVType() {
2850 return RISCVOperand::createSMTVType(VType: XSMTVTypeMode::SMTVTypeMode::SMT_I8,
2851 S: SMLoc());
2852}
2853
2854ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2855 const AsmToken &Tok = getLexer().getTok();
2856
2857 if (Tok.is(K: AsmToken::Integer)) {
2858 if (Tok.getIntVal() != 0)
2859 goto ParseFail;
2860
2861 Operands.push_back(Elt: RISCVOperand::createFenceArg(Val: 0, S: getLoc()));
2862 Lex();
2863 return ParseStatus::Success;
2864 }
2865
2866 if (Tok.is(K: 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':
2881 Imm |= RISCVFenceField::I;
2882 break;
2883 case 'o':
2884 Imm |= RISCVFenceField::O;
2885 break;
2886 case 'r':
2887 Imm |= RISCVFenceField::R;
2888 break;
2889 case 'w':
2890 Imm |= RISCVFenceField::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(Elt: RISCVOperand::createFenceArg(Val: Imm, S: getLoc()));
2905 Lex();
2906 return ParseStatus::Success;
2907 }
2908
2909ParseFail:
2910 return TokError(Msg: "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(T: AsmToken::LParen, Msg: "expected '('"))
2916 return ParseStatus::Failure;
2917 Operands.push_back(Elt: RISCVOperand::createToken(Str: "(", S: getLoc()));
2918
2919 if (!parseRegister(Operands).isSuccess())
2920 return Error(L: getLoc(), Msg: "expected register");
2921
2922 if (parseToken(T: AsmToken::RParen, Msg: "expected ')'"))
2923 return ParseStatus::Failure;
2924 Operands.push_back(Elt: RISCVOperand::createToken(Str: ")", S: 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(K: 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(V&: ImmVal,
2957 ErrMsg: "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(Val: MCConstantExpr::create(Value: ImmVal, Ctx&: getContext()),
2965 S: ImmStart, E: ImmEnd, IsRV64: isRV64());
2966 }
2967
2968 if (parseToken(T: AsmToken::LParen,
2969 Msg: 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(L: getLoc(), Msg: "expected register");
2975
2976 if (parseToken(T: AsmToken::RParen, Msg: "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 L: OptionalImmOp->getStartLoc(), Msg: "optional integer offset must be 0",
2983 Range: 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(Name: OffsetRegName);
2996 if (!OffsetReg ||
2997 !getRISCVMCRegisterClass(RC: RISCV::GPRRegClassID).contains(Reg: OffsetReg))
2998 return Error(L: getLoc(), Msg: "expected GPR register");
2999 getLexer().Lex();
3000
3001 if (parseToken(T: AsmToken::LParen, Msg: "expected '(' or invalid operand"))
3002 return ParseStatus::Failure;
3003
3004 if (getLexer().getKind() != AsmToken::Identifier)
3005 return Error(L: getLoc(), Msg: "expected GPR register");
3006
3007 StringRef BaseRegName = getLexer().getTok().getIdentifier();
3008 MCRegister BaseReg = matchRegisterNameHelper(Name: BaseRegName);
3009 if (!BaseReg ||
3010 !getRISCVMCRegisterClass(RC: RISCV::GPRRegClassID).contains(Reg: BaseReg))
3011 return Error(L: getLoc(), Msg: "expected GPR register");
3012 getLexer().Lex();
3013
3014 if (parseToken(T: AsmToken::RParen, Msg: "expected ')'"))
3015 return ParseStatus::Failure;
3016
3017 Operands.push_back(Elt: 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(K: 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(K: AsmToken::Identifier))
3042 return Error(L: getLoc(), Msg: "invalid register");
3043
3044 StringRef RegName = getTok().getIdentifier();
3045 MCRegister Reg = matchRegisterNameHelper(Name: RegName);
3046 if (!Reg)
3047 return Error(L: getLoc(), Msg: "invalid register");
3048
3049 if (!RegEnd) {
3050 UsesXRegs = RegName[0] == 'x';
3051 if (Reg != RISCV::X1)
3052 return Error(L: getLoc(), Msg: "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(L: getLoc(), Msg: 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(L: getLoc(), Msg: "register must be 'x18'");
3060 } else {
3061 return Error(L: getLoc(), Msg: "too many register ranges");
3062 }
3063
3064 RegEnd = Reg;
3065
3066 Lex();
3067
3068 SMLoc MinusLoc = getLoc();
3069 if (parseOptionalToken(T: AsmToken::Minus)) {
3070 if (RegEnd == RISCV::X1)
3071 return Error(L: MinusLoc, Msg: Twine("register '") + (UsesXRegs ? "x1" : "ra") +
3072 "' cannot start a multiple register range");
3073
3074 if (getTok().isNot(K: AsmToken::Identifier))
3075 return Error(L: getLoc(), Msg: "invalid register");
3076
3077 StringRef RegName = getTok().getIdentifier();
3078 MCRegister Reg = matchRegisterNameHelper(Name: RegName);
3079 if (!Reg)
3080 return Error(L: getLoc(), Msg: "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(L: getLoc(), Msg: "register must be 'x9'");
3088 return Error(L: getLoc(), Msg: "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(L: getLoc(),
3093 Msg: "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(T: AsmToken::Comma));
3102
3103 if (parseToken(T: AsmToken::RCurly, Msg: "expected ',' or '}'"))
3104 return ParseStatus::Failure;
3105
3106 if (RegEnd == RISCV::X26)
3107 return Error(L: S, Msg: "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
3108 "x18-x26}' is not supported");
3109
3110 auto Encode = RISCVZC::encodeRegList(EndReg: RegEnd, IsRVE: isRVE());
3111 assert(Encode != RISCVZC::INVALID_RLIST);
3112
3113 if (MustIncludeS0 && Encode == RISCVZC::RA)
3114 return Error(L: S, Msg: "register list must include 's0' or 'x8'");
3115
3116 Operands.push_back(Elt: RISCVOperand::createRegList(RlistEncode: 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(T: AsmToken::Minus);
3125
3126 if (getTok().isNot(K: 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(RlistVal: RlistEncode, IsRV64: 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;
3146 std::swap(a&: Lower, b&: Upper);
3147 }
3148 return generateImmOutOfRangeError(ErrorLoc: S, Lower, Upper,
3149 Msg: "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(Elt: 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, AllowParens: 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(K: 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(L: getLoc(), Msg: "unknown operand");
3186 return true;
3187}
3188
3189bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,
3190 StringRef Name, SMLoc NameLoc,
3191 OperandVector &Operands) {
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(Mnemonic&: Name, Features: AvailableFeatures, VariantID: 0);
3198
3199 // First operand is token for instruction
3200 Operands.push_back(Elt: RISCVOperand::createToken(Str: Name, S: NameLoc));
3201
3202 // If there are no more operands, then finish
3203 if (getLexer().is(K: AsmToken::EndOfStatement)) {
3204 getParser().Lex(); // Consume the EndOfStatement.
3205 return false;
3206 }
3207
3208 // Parse first operand
3209 if (parseOperand(Operands, Mnemonic: Name))
3210 return true;
3211
3212 // Parse until end of statement, consuming commas between operands
3213 while (parseOptionalToken(T: AsmToken::Comma)) {
3214 // Parse next operand
3215 if (parseOperand(Operands, Mnemonic: Name))
3216 return true;
3217 }
3218
3219 if (getParser().parseEOL(ErrMsg: "unexpected token")) {
3220 getParser().eatToEndOfStatement();
3221 return true;
3222 }
3223 return false;
3224}
3225
3226bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
3227 RISCV::Specifier &Kind) {
3228 Kind = RISCV::S_None;
3229 if (const auto *RE = dyn_cast<MCSpecifierExpr>(Val: Expr)) {
3230 Kind = RE->getSpecifier();
3231 Expr = RE->getSubExpr();
3232 }
3233
3234 MCValue Res;
3235 if (Expr->evaluateAsRelocatable(Res, Asm: 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, Asm: 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(L: 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)
3268 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Ext: Feature.key()))
3269 clearFeatureBits(Feature: Feature.Value, FeatureString: 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(E: ParseResult.takeError(), Handlers: [&](llvm::StringError &ErrMsg) {
3278 OutputErrMsg << "invalid arch name '" << Arch << "', "
3279 << ErrMsg.getMessage();
3280 });
3281
3282 return Error(L: Loc, Msg: OutputErrMsg.str());
3283 }
3284 auto &ISAInfo = *ParseResult;
3285
3286 for (auto &Feature : AllFeatures)
3287 if (ISAInfo->hasExtension(Ext: Feature.key()))
3288 setFeatureBits(Feature: Feature.Value, FeatureString: Feature.key());
3289
3290 if (FromOptionDirective) {
3291 if (ISAInfo->getXLen() == 32 && isRV64())
3292 return Error(L: Loc, Msg: "bad arch string switching from rv64 to rv32");
3293 else if (ISAInfo->getXLen() == 64 && !isRV64())
3294 return Error(L: Loc, Msg: "bad arch string switching from rv32 to rv64");
3295 }
3296
3297 if (ISAInfo->getXLen() == 32)
3298 clearFeatureBits(Feature: RISCV::Feature64Bit, FeatureString: "64bit");
3299 else if (ISAInfo->getXLen() == 64)
3300 setFeatureBits(Feature: RISCV::Feature64Bit, FeatureString: "64bit");
3301 else
3302 return Error(L: Loc, Msg: "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(T: AsmToken::Identifier, Msg: "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(L: StartLoc, Msg: ".option pop with no .option push");
3336
3337 return false;
3338 }
3339
3340 if (Option == "arch") {
3341 SmallVector<RISCVOptionArchArg> Args;
3342 do {
3343 if (Parser.parseComma())
3344 return true;
3345
3346 RISCVOptionArchArgType Type;
3347 if (parseOptionalToken(T: AsmToken::Plus))
3348 Type = RISCVOptionArchArgType::Plus;
3349 else if (parseOptionalToken(T: AsmToken::Minus))
3350 Type = RISCVOptionArchArgType::Minus;
3351 else if (!Args.empty())
3352 return Error(L: Parser.getTok().getLoc(),
3353 Msg: "unexpected token, expected + or -");
3354 else
3355 Type = RISCVOptionArchArgType::Full;
3356
3357 if (Parser.getTok().isNot(K: AsmToken::Identifier))
3358 return Error(L: Parser.getTok().getLoc(),
3359 Msg: "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, FromOptionDirective: true))
3368 return true;
3369
3370 Args.emplace_back(Args&: Type, Args&: Result);
3371 break;
3372 }
3373
3374 if (isDigit(C: Arch.back()))
3375 return Error(
3376 L: Loc, Msg: "extension version number parsing not currently implemented");
3377
3378 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Ext: Arch);
3379 if (!enableExperimentalExtension() &&
3380 StringRef(Feature).starts_with(Prefix: "experimental-"))
3381 return Error(L: Loc, Msg: "unexpected experimental extensions");
3382 const auto &AllFeatures = getSTI().getAllProcessorFeatures();
3383 auto Ext = llvm::lower_bound(Range: AllFeatures, Value&: Feature);
3384 if (Ext == std::end(cont: AllFeatures) || StringRef(Ext->key()) != Feature)
3385 return Error(L: Loc, Msg: "unknown extension feature");
3386
3387 Args.emplace_back(Args&: Type, Args: Arch.str());
3388
3389 if (Type == RISCVOptionArchArgType::Plus) {
3390 FeatureBitset OldFeatureBits = STI->getFeatureBits();
3391
3392 setFeatureBits(Feature: Ext->Value, FeatureString: Ext->key());
3393 auto ParseResult = RISCVFeatures::parseFeatureBits(STI: *STI);
3394 if (!ParseResult) {
3395 copySTI().setFeatureBits(OldFeatureBits);
3396 setAvailableFeatures(ComputeAvailableFeatures(FB: OldFeatureBits));
3397
3398 std::string Buffer;
3399 raw_string_ostream OutputErrMsg(Buffer);
3400 handleAllErrors(E: ParseResult.takeError(), Handlers: [&](llvm::StringError &ErrMsg) {
3401 OutputErrMsg << ErrMsg.getMessage();
3402 });
3403
3404 return Error(L: Loc, Msg: 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: Feature.Value) &&
3413 Feature.Implies.test(I: Ext->Value))
3414 return Error(L: Loc, Msg: Twine("can't disable ") + Ext->key() +
3415 " extension; " + Feature.key() +
3416 " extension requires " + Ext->key() +
3417 " extension");
3418 }
3419
3420 clearFeatureBits(Feature: Ext->Value, FeatureString: Ext->key());
3421 }
3422 } while (Parser.getTok().isNot(K: AsmToken::EndOfStatement));
3423
3424 if (Parser.parseEOL())
3425 return true;
3426
3427 getTargetStreamer().emitDirectiveOptionArch(Args);
3428
3429 if (auto ParseResult = RISCVFeatures::parseFeatureBits(STI: *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(Feature: RISCV::FeatureExactAssembly, FeatureString: "exact-asm");
3440 clearFeatureBits(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3441 return false;
3442 }
3443
3444 if (Option == "noexact") {
3445 if (Parser.parseEOL())
3446 return true;
3447
3448 getTargetStreamer().emitDirectiveOptionNoExact();
3449 clearFeatureBits(Feature: RISCV::FeatureExactAssembly, FeatureString: "exact-asm");
3450 setFeatureBits(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3451 return false;
3452 }
3453
3454 if (Option == "rvc") {
3455 if (Parser.parseEOL())
3456 return true;
3457
3458 getTargetStreamer().emitDirectiveOptionRVC();
3459 setFeatureBits(Feature: RISCV::FeatureStdExtC, FeatureString: "c");
3460 if (auto ParseResult = RISCVFeatures::parseFeatureBits(STI: *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(Feature: RISCV::FeatureStdExtC, FeatureString: "c");
3471 clearFeatureBits(Feature: RISCV::FeatureStdExtZca, FeatureString: "zca");
3472 if (auto ParseResult = RISCVFeatures::parseFeatureBits(STI: *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(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3501 return false;
3502 }
3503
3504 if (Option == "norelax") {
3505 if (Parser.parseEOL())
3506 return true;
3507
3508 getTargetStreamer().emitDirectiveOptionNoRelax();
3509 clearFeatureBits(Feature: RISCV::FeatureRelax, FeatureString: "relax");
3510 return false;
3511 }
3512
3513 // Unknown option.
3514 Warning(L: Parser.getTok().getLoc(),
3515 Msg: "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(K: AsmToken::Identifier)) {
3531 StringRef Name = Parser.getTok().getIdentifier();
3532 std::optional<unsigned> Ret =
3533 ELFAttrs::attrTypeFromString(tag: Name, tagNameMap: RISCVAttrs::getRISCVAttributeTags());
3534 if (!Ret)
3535 return Error(L: TagLoc, Msg: "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(Res&: AttrExpr))
3543 return true;
3544
3545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: AttrExpr);
3546 if (check(P: !CE, Loc: TagLoc, Msg: "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(Res&: ValueExpr))
3568 return true;
3569
3570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: ValueExpr);
3571 if (!CE)
3572 return Error(L: ValueExprLoc, Msg: "expected numeric constant");
3573 IntegerValue = CE->getValue();
3574 } else {
3575 if (Parser.getTok().isNot(K: AsmToken::String))
3576 return Error(L: Parser.getTok().getLoc(), Msg: "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(Attribute: Tag, Value: IntegerValue);
3587 else if (Tag != RISCVAttrs::ARCH)
3588 getTargetStreamer().emitTextAttribute(Attribute: Tag, String: StringValue);
3589 else {
3590 std::string Result;
3591 if (resetToArch(Arch: StringValue, Loc: ValueExprLoc, Result, FromOptionDirective: false))
3592 return true;
3593
3594 // Then emit the arch string.
3595 getTargetStreamer().emitTextAttribute(Attribute: Tag, String: 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
3605bool isValidInsnFormat(StringRef Format, const MCSubtargetInfo &STI) {
3606 return StringSwitch<bool>(Format)
3607 .Cases(CaseStrings: {"r", "r4", "i", "b", "sb", "u", "j", "uj", "s"}, Value: true)
3608 .Cases(CaseStrings: {"cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj"},
3609 Value: STI.hasFeature(Feature: RISCV::FeatureStdExtZca))
3610 .Cases(CaseStrings: {"qc.eai", "qc.ei", "qc.eb", "qc.ej", "qc.es"},
3611 Value: !STI.hasFeature(Feature: RISCV::Feature64Bit))
3612 .Default(Value: 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(Res&: Format)) {
3626 // Try parsing .insn [ length , ] value
3627 std::optional<int64_t> Length;
3628 int64_t Value = 0;
3629 if (Parser.parseAbsoluteExpression(Res&: Value))
3630 return true;
3631 if (Parser.parseOptionalToken(T: AsmToken::Comma)) {
3632 Length = Value;
3633 if (Parser.parseAbsoluteExpression(Res&: Value))
3634 return true;
3635
3636 if (*Length == 0 || (*Length % 2) != 0)
3637 return Error(L: ErrorLoc,
3638 Msg: "instruction lengths must be a non-zero multiple of two");
3639
3640 // TODO: Support Instructions > 64 bits.
3641 if (*Length > 8)
3642 return Error(L: ErrorLoc,
3643 Msg: "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(L: ErrorLoc,
3656 Msg: "instruction length does not match the encoding");
3657
3658 if (!isUIntN(N: *Length * 8, x: Value))
3659 return Error(L: ErrorLoc, Msg: "encoding value does not fit into instruction");
3660 } else {
3661 if (!isUIntN(N: EncodingDerivedLength * 8, x: Value))
3662 return Error(L: ErrorLoc, Msg: "encoding value does not fit into instruction");
3663 }
3664
3665 if (!getSTI().hasFeature(Feature: RISCV::FeatureStdExtZca) &&
3666 (EncodingDerivedLength == 2))
3667 return Error(L: ErrorLoc, Msg: "compressed instructions are not allowed");
3668
3669 if (getParser().parseEOL(ErrMsg: "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(S&: getStreamer(), Inst: MCInstBuilder(Opcode).addImm(Val: Value));
3696 return false;
3697 }
3698
3699 if (!isValidInsnFormat(Format, STI: getSTI()))
3700 return Error(L: ErrorLoc, Msg: "invalid instruction format");
3701
3702 std::string FormatName = (".insn_" + Format).str();
3703
3704 ParseInstructionInfo Info;
3705 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
3706
3707 if (parseInstruction(Info, Name: FormatName, NameLoc: L, Operands))
3708 return true;
3709
3710 unsigned Opcode;
3711 uint64_t ErrorInfo;
3712 return matchAndEmitInstruction(IDLoc: L, Opcode, Operands, Out&: 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(Res&: Name))
3722 return TokError(Msg: "expected symbol name");
3723 if (parseEOL())
3724 return true;
3725 getTargetStreamer().emitDirectiveVariantCC(
3726 Symbol&: *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(Feature: RISCV::FeatureExactAssembly))
3735 Res = RISCVRVC::compress(OutInst&: CInst, MI: Inst, STI);
3736 if (Res)
3737 ++RISCVNumInstrsCompressed;
3738 S.emitInstruction(Inst: (Res ? CInst : Inst), STI);
3739}
3740
3741void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3742 MCStreamer &Out) {
3743 SmallVector<MCInst, 8> Seq;
3744 RISCVMatInt::generateMCInstSeq(Val: Value, STI: getSTI(), DestReg, Insts&: Seq);
3745
3746 for (MCInst &Inst : Seq) {
3747 emitToStreamer(S&: 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(Name: "pcrel_hi");
3762 Out.emitLabel(Symbol: TmpLabel);
3763
3764 const auto *SymbolHi = MCSpecifierExpr::create(Expr: Symbol, S: VKHi, Ctx);
3765 emitToStreamer(S&: Out,
3766 Inst: MCInstBuilder(RISCV::AUIPC).addReg(Reg: TmpReg).addExpr(Val: SymbolHi));
3767
3768 const MCExpr *RefToLinkTmpLabel = MCSpecifierExpr::create(
3769 Expr: MCSymbolRefExpr::create(Symbol: TmpLabel, Ctx), S: RISCV::S_PCREL_LO, Ctx);
3770
3771 emitToStreamer(S&: Out, Inst: MCInstBuilder(SecondOpcode)
3772 .addReg(Reg: DestReg)
3773 .addReg(Reg: TmpReg)
3774 .addExpr(Val: 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(i: 0).getReg();
3786 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3787 if (STI->hasFeature(Feature: RISCV::Feature32Bit) &&
3788 STI->hasFeature(Feature: RISCV::FeatureVendorXqcili))
3789 emitToStreamer(
3790 S&: Out, Inst: MCInstBuilder(RISCV::QC_E_LI).addReg(Reg: DestReg).addExpr(Val: Symbol));
3791 else
3792 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: RISCV::S_PCREL_HI, SecondOpcode: 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(i: 0).getReg();
3805 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3806 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3807 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: 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(i: 0).getReg();
3835 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3836 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3837 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: 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(i: 0).getReg();
3850 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
3851 emitAuipcInstPair(DestReg, TmpReg: DestReg, Symbol, VKHi: ELF::R_RISCV_TLS_GD_HI20,
3852 SecondOpcode: 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(i: DestRegOpIdx).getReg();
3867 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3868 MCRegister TmpReg = Inst.getOperand(i: 0).getReg();
3869
3870 // If TmpReg is a GPR pair, get the even register.
3871 if (getRISCVMCRegisterClass(RC: RISCV::GPRPairRegClassID).contains(Reg: TmpReg)) {
3872 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3873 TmpReg = RI->getSubReg(Reg: TmpReg, Idx: RISCV::sub_gpr_even);
3874 }
3875
3876 const MCExpr *Symbol = Inst.getOperand(i: SymbolOpIdx).getExpr();
3877 emitAuipcInstPair(DestReg, TmpReg, Symbol, VKHi: RISCV::S_PCREL_HI, SecondOpcode: 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(i: 0).getReg();
3892 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3893 const MCExpr *Symbol = Inst.getOperand(i: SymbolOpIdx).getExpr();
3894
3895 emitToStreamer(S&: Out,
3896 Inst: MCInstBuilder(RISCV::QC_E_LI).addReg(Reg: AddrReg).addExpr(Val: Symbol));
3897
3898 MCContext &Ctx = getContext();
3899 const MCExpr *AccessExpr =
3900 MCSpecifierExpr::create(Expr: Symbol, S: RISCV::S_QC_ACCESS, Ctx);
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 = {.Opcode: RISCV::PseudoQCAccessC_LBU, .Feature: RISCV::FeatureStdExtZcb};
3915 break;
3916 case RISCV::PseudoQCAccessLH:
3917 Compressed = {.Opcode: RISCV::PseudoQCAccessC_LH, .Feature: RISCV::FeatureStdExtZcb};
3918 break;
3919 case RISCV::PseudoQCAccessLHU:
3920 Compressed = {.Opcode: RISCV::PseudoQCAccessC_LHU, .Feature: RISCV::FeatureStdExtZcb};
3921 break;
3922 case RISCV::PseudoQCAccessLW:
3923 Compressed = {.Opcode: RISCV::PseudoQCAccessC_LW, .Feature: RISCV::FeatureStdExtZca};
3924 break;
3925 case RISCV::PseudoQCAccessSB:
3926 Compressed = {.Opcode: RISCV::PseudoQCAccessC_SB, .Feature: RISCV::FeatureStdExtZcb};
3927 break;
3928 case RISCV::PseudoQCAccessSH:
3929 Compressed = {.Opcode: RISCV::PseudoQCAccessC_SH, .Feature: RISCV::FeatureStdExtZcb};
3930 break;
3931 case RISCV::PseudoQCAccessSW:
3932 Compressed = {.Opcode: RISCV::PseudoQCAccessC_SW, .Feature: 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(RC: RISCV::GPRCRegClassID).contains(Reg: AddrReg);
3940 if (HasTmpReg && CanUseGPRC) {
3941 MCRegister DataReg = Inst.getOperand(i: 1).getReg();
3942 CanUseGPRC =
3943 getRISCVMCRegisterClass(RC: RISCV::GPRCRegClassID).contains(Reg: DataReg);
3944 }
3945
3946 bool UseCompressed =
3947 Compressed && getSTI().hasFeature(Feature: Compressed->Feature) && CanUseGPRC;
3948
3949 unsigned ActualOpcode = UseCompressed ? Compressed->Opcode : Opcode;
3950 if (HasTmpReg) {
3951 MCRegister DataReg = Inst.getOperand(i: 1).getReg();
3952 emitToStreamer(S&: Out, Inst: MCInstBuilder(ActualOpcode)
3953 .addReg(Reg: DataReg)
3954 .addReg(Reg: AddrReg)
3955 .addImm(Val: 0)
3956 .addExpr(Val: AccessExpr));
3957 } else {
3958 emitToStreamer(S&: Out, Inst: MCInstBuilder(ActualOpcode)
3959 .addReg(Reg: AddrReg)
3960 .addReg(Reg: AddrReg)
3961 .addImm(Val: 0)
3962 .addExpr(Val: 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(i: 0);
3977 const MCOperand &SourceReg = Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(RISCV::SLLI)
3985 .addOperand(Op: DestReg)
3986 .addOperand(Op: SourceReg)
3987 .addImm(Val: ShAmt));
3988
3989 emitToStreamer(S&: Out, Inst: MCInstBuilder(SecondOpcode)
3990 .addOperand(Op: DestReg)
3991 .addOperand(Op: DestReg)
3992 .addImm(Val: ShAmt));
3993}
3994
3995void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3996 MCStreamer &Out) {
3997 if (Inst.getNumOperands() == 4 && !Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(Opcode)
4003 .addOperand(Op: Inst.getOperand(i: 0))
4004 .addOperand(Op: Inst.getOperand(i: 1))
4005 .addOperand(Op: Inst.getOperand(i: 2))
4006 .addReg(Reg: MCRegister())
4007 .setLoc(IDLoc));
4008 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMNAND_MM)
4009 .addOperand(Op: Inst.getOperand(i: 0))
4010 .addOperand(Op: Inst.getOperand(i: 0))
4011 .addOperand(Op: Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(Opcode)
4022 .addOperand(Op: Inst.getOperand(i: 0))
4023 .addOperand(Op: Inst.getOperand(i: 1))
4024 .addOperand(Op: Inst.getOperand(i: 2))
4025 .addOperand(Op: Inst.getOperand(i: 3))
4026 .setLoc(IDLoc));
4027 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMXOR_MM)
4028 .addOperand(Op: Inst.getOperand(i: 0))
4029 .addOperand(Op: Inst.getOperand(i: 0))
4030 .addReg(Reg: RISCV::V0)
4031 .setLoc(IDLoc));
4032 } else if (Inst.getNumOperands() == 5 &&
4033 Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(Opcode)
4041 .addOperand(Op: Inst.getOperand(i: 1))
4042 .addOperand(Op: Inst.getOperand(i: 2))
4043 .addOperand(Op: Inst.getOperand(i: 3))
4044 .addReg(Reg: MCRegister())
4045 .setLoc(IDLoc));
4046 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMANDN_MM)
4047 .addOperand(Op: Inst.getOperand(i: 0))
4048 .addOperand(Op: Inst.getOperand(i: 0))
4049 .addOperand(Op: Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(Opcode)
4060 .addOperand(Op: Inst.getOperand(i: 1))
4061 .addOperand(Op: Inst.getOperand(i: 2))
4062 .addOperand(Op: Inst.getOperand(i: 3))
4063 .addReg(Reg: MCRegister())
4064 .setLoc(IDLoc));
4065 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMANDN_MM)
4066 .addOperand(Op: Inst.getOperand(i: 1))
4067 .addReg(Reg: RISCV::V0)
4068 .addOperand(Op: Inst.getOperand(i: 1))
4069 .setLoc(IDLoc));
4070 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMANDN_MM)
4071 .addOperand(Op: Inst.getOperand(i: 0))
4072 .addOperand(Op: Inst.getOperand(i: 0))
4073 .addReg(Reg: RISCV::V0)
4074 .setLoc(IDLoc));
4075 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::VMOR_MM)
4076 .addOperand(Op: Inst.getOperand(i: 0))
4077 .addOperand(Op: Inst.getOperand(i: 1))
4078 .addOperand(Op: Inst.getOperand(i: 0))
4079 .setLoc(IDLoc));
4080 }
4081}
4082
4083bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
4084 OperandVector &Operands) {
4085 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
4086 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
4087 if (Inst.getOperand(i: 2).getReg() != RISCV::X4) {
4088 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
4089 return Error(L: ErrorLoc, Msg: "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,
4097 OperandVector &Operands) {
4098 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
4099 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
4100 if (Inst.getOperand(i: 0).getReg() != RISCV::X5) {
4101 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
4102 return Error(L: ErrorLoc, Msg: "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(Reg: MCRegister(), S: llvm::SMLoc(), E: llvm::SMLoc());
4111}
4112
4113std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
4114 return RISCVOperand::createFRMArg(FRM: RISCVFPRndMode::RoundingMode::DYN,
4115 S: llvm::SMLoc());
4116}
4117
4118std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
4119 return RISCVOperand::createFRMArg(FRM: RISCVFPRndMode::RoundingMode::RNE,
4120 S: llvm::SMLoc());
4121}
4122
4123std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultZeroOffset() {
4124 return RISCVOperand::createExpr(Val: MCConstantExpr::create(Value: 0, Ctx&: getContext()),
4125 S: llvm::SMLoc(), E: llvm::SMLoc(), IsRV64: 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
4198unsigned getLMULFromVectorRegister(MCRegister Reg) {
4199 if (getRISCVMCRegisterClass(RC: RISCV::VRM2RegClassID).contains(Reg))
4200 return 2;
4201 if (getRISCVMCRegisterClass(RC: RISCV::VRM4RegClassID).contains(Reg))
4202 return 4;
4203 if (getRISCVMCRegisterClass(RC: 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,
4223 OperandVector &Operands) {
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(i: 0).getReg();
4229 MCRegister TempReg = Inst.getOperand(i: 1).getReg();
4230 if (DestReg == TempReg) {
4231 SMLoc Loc = Operands.back()->getStartLoc();
4232 return Error(L: Loc, Msg: "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(i: 0).getReg();
4239 MCRegister MaskReg = Inst.getOperand(i: 3).getReg();
4240 if (MaskReg == RISCV::V0 && DestReg == RISCV::V0) {
4241 SMLoc Loc = Operands.back()->getStartLoc();
4242 return Error(L: Loc, Msg: "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(i: 0).getReg();
4251 MCRegister Rd2 = Inst.getOperand(i: 1).getReg();
4252 MCRegister Rs1 = Inst.getOperand(i: 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(L: Loc, Msg: "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(i: 0).getReg();
4262 MCRegister Rs2 = Inst.getOperand(i: 1).getReg();
4263 if (Rs1 == Rs2) {
4264 SMLoc Loc = Operands[1]->getStartLoc();
4265 return Error(L: Loc, Msg: "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(i: OperandIdx).getReg() == RISCV::V0)
4273 return Error(L: Operands[ParsedIdx]->getStartLoc(),
4274 Msg: "vd, vs1, and vs2 cannot overlap v0.scale");
4275 return false;
4276 };
4277
4278 int DestIdx =
4279 RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vd);
4280 int VS1Idx =
4281 RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vs1);
4282 int VS2Idx =
4283 RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: 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(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vd);
4298 MCRegister DestReg = Inst.getOperand(i: 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(Reg: DestReg);
4311 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4312 unsigned DestEncoding = RI->getEncodingValue(Reg: DestReg);
4313 if (MCID.TSFlags & RISCVII::VS2Constraint) {
4314 int VS2Idx =
4315 RISCV::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vs2);
4316 assert(VS2Idx >= 0 && "No vs2 operand?");
4317 unsigned CheckEncoding =
4318 RI->getEncodingValue(Reg: Inst.getOperand(i: VS2Idx).getReg());
4319 unsigned NF = getNFforLXSEG(Opcode);
4320 for (unsigned i = 0; i < std::max(a: NF, b: Lmul); i++) {
4321 if ((DestEncoding + i) == CheckEncoding)
4322 return Error(L: Loc, Msg: "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(Opcode: Inst.getOpcode(), Name: 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(Reg: Inst.getOperand(i: VS1Idx).getReg());
4334 for (unsigned i = 0; i < Lmul; i++) {
4335 if ((DestEncoding + i) == CheckEncoding)
4336 return Error(L: Loc,
4337 Msg: "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(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vm);
4345 assert(VMIdx >= 0 && "No vm operand?");
4346
4347 if (DestReg == RISCV::V0) {
4348 if (MCID.operands()[Inst.getNumOperands() - 1].OperandType !=
4349 RISCVOp::OPERAND_VMASK)
4350 return Error(L: Loc, Msg: "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(i: VMIdx).getReg();
4357 assert((!CheckReg.isValid() || CheckReg == RISCV::V0) &&
4358 "Unexpected mask operand register");
4359 if (CheckReg.isValid())
4360 return Error(L: Loc, Msg: "the destination vector register group cannot overlap"
4361 " the mask register");
4362 }
4363 }
4364
4365 if (MCID.TSFlags & RISCVII::SMTConstraintMask) {
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(Opcode: Inst.getOpcode(), Name: RISCV::OpName::vmask);
4370 MCRegister MaskReg = Inst.getOperand(i: VMaskIdx).getReg();
4371 if (MaskReg != RISCV::V0 && MaskReg != RISCV::V1)
4372 return Error(L: Operands[VMaskIdx]->getStartLoc(),
4373 Msg: "vmask operand only supports v0 or v1");
4374
4375 unsigned MaskEnc = RI->getEncodingValue(Reg: 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(Opcode: Inst.getOpcode(), Name: OpN);
4380 if (Idx < 0 || !Inst.getOperand(i: Idx).isReg())
4381 continue;
4382 MCRegister Reg = Inst.getOperand(i: 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(L: Loc, Msg: Twine("register conflicts with vmask register ") +
4389 RISCVInstPrinter::getRegisterName(Reg: MaskReg));
4390 }
4391 }
4392 }
4393 }
4394
4395 return false;
4396}
4397
4398bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
4399 OperandVector &Operands,
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(i: 2).getImm() == 0)
4408 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::C_NOP));
4409 else
4410 emitToStreamer(
4411 S&: Out, Inst: MCInstBuilder(RISCV::C_NOP_HINT).addOperand(Op: Inst.getOperand(i: 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(i: 2).getReg() != RISCV::X0)
4417 break;
4418 if (getSTI().hasFeature(Feature: RISCV::Feature64Bit))
4419 break;
4420 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::ZEXT_H_RV32)
4421 .addOperand(Op: Inst.getOperand(i: 0))
4422 .addOperand(Op: Inst.getOperand(i: 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(i: 2).getReg() != RISCV::X0)
4428 break;
4429 emitToStreamer(S&: Out, Inst: MCInstBuilder(RISCV::ZEXT_H_RV64)
4430 .addOperand(Op: Inst.getOperand(i: 0))
4431 .addOperand(Op: Inst.getOperand(i: 1)));
4432 return false;
4433 }
4434 case RISCV::PseudoLLAImm:
4435 case RISCV::PseudoLAImm:
4436 case RISCV::PseudoLI: {
4437 MCRegister Reg = Inst.getOperand(i: 0).getReg();
4438 const MCOperand &Op1 = Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(RISCV::ADDI)
4443 .addReg(Reg)
4444 .addReg(Reg: RISCV::X0)
4445 .addExpr(Val: Op1.getExpr()));
4446 return false;
4447 }
4448 int64_t Imm = Inst.getOperand(i: 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>(x: Imm);
4454 emitLoadImm(DestReg: Reg, Value: 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, Opcode: RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
4474 return false;
4475 case RISCV::PseudoLBU:
4476 emitLoadStoreSymbol(Inst, Opcode: RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
4477 return false;
4478 case RISCV::PseudoLH:
4479 emitLoadStoreSymbol(Inst, Opcode: RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
4480 return false;
4481 case RISCV::PseudoLHU:
4482 emitLoadStoreSymbol(Inst, Opcode: RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
4483 return false;
4484 case RISCV::PseudoLW:
4485 emitLoadStoreSymbol(Inst, Opcode: RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
4486 return false;
4487 case RISCV::PseudoLWU:
4488 emitLoadStoreSymbol(Inst, Opcode: RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
4489 return false;
4490 case RISCV::PseudoLD:
4491 emitLoadStoreSymbol(Inst, Opcode: RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
4492 return false;
4493 case RISCV::PseudoLD_RV32:
4494 emitLoadStoreSymbol(Inst, Opcode: RISCV::LD_RV32, IDLoc, Out, /*HasTmpReg=*/false);
4495 return false;
4496 case RISCV::PseudoFLH:
4497 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
4498 return false;
4499 case RISCV::PseudoFLW:
4500 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
4501 return false;
4502 case RISCV::PseudoFLD:
4503 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
4504 return false;
4505 case RISCV::PseudoFLQ:
4506 emitLoadStoreSymbol(Inst, Opcode: RISCV::FLQ, IDLoc, Out, /*HasTmpReg=*/true);
4507 return false;
4508 case RISCV::PseudoSB:
4509 emitLoadStoreSymbol(Inst, Opcode: RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
4510 return false;
4511 case RISCV::PseudoSH:
4512 emitLoadStoreSymbol(Inst, Opcode: RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
4513 return false;
4514 case RISCV::PseudoSW:
4515 emitLoadStoreSymbol(Inst, Opcode: RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
4516 return false;
4517 case RISCV::PseudoSD:
4518 emitLoadStoreSymbol(Inst, Opcode: RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
4519 return false;
4520 case RISCV::PseudoSD_RV32:
4521 emitLoadStoreSymbol(Inst, Opcode: RISCV::SD_RV32, IDLoc, Out, /*HasTmpReg=*/true);
4522 return false;
4523 case RISCV::PseudoQC_E_LB:
4524 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessLB, IDLoc, Out,
4525 /*HasTmpReg=*/false);
4526 return false;
4527 case RISCV::PseudoQC_E_LBU:
4528 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessLBU, IDLoc, Out,
4529 /*HasTmpReg=*/false);
4530 return false;
4531 case RISCV::PseudoQC_E_LH:
4532 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessLH, IDLoc, Out,
4533 /*HasTmpReg=*/false);
4534 return false;
4535 case RISCV::PseudoQC_E_LHU:
4536 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessLHU, IDLoc, Out,
4537 /*HasTmpReg=*/false);
4538 return false;
4539 case RISCV::PseudoQC_E_LW:
4540 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessLW, IDLoc, Out,
4541 /*HasTmpReg=*/false);
4542 return false;
4543 case RISCV::PseudoQC_E_SB:
4544 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessSB, IDLoc, Out,
4545 /*HasTmpReg=*/true);
4546 return false;
4547 case RISCV::PseudoQC_E_SH:
4548 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessSH, IDLoc, Out,
4549 /*HasTmpReg=*/true);
4550 return false;
4551 case RISCV::PseudoQC_E_SW:
4552 emitQCELILoadStoreSymbol(Inst, Opcode: RISCV::PseudoQCAccessSW, IDLoc, Out,
4553 /*HasTmpReg=*/true);
4554 return false;
4555 case RISCV::PseudoFSH:
4556 emitLoadStoreSymbol(Inst, Opcode: RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
4557 return false;
4558 case RISCV::PseudoFSW:
4559 emitLoadStoreSymbol(Inst, Opcode: RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
4560 return false;
4561 case RISCV::PseudoFSD:
4562 emitLoadStoreSymbol(Inst, Opcode: RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
4563 return false;
4564 case RISCV::PseudoFSQ:
4565 emitLoadStoreSymbol(Inst, Opcode: 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, Opcode: RISCV::VMSLTU_VX, IDLoc, Out);
4590 return false;
4591 case RISCV::PseudoVMSGE_VX_M:
4592 case RISCV::PseudoVMSGE_VX_M_T:
4593 emitVMSGE(Inst, Opcode: 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(i: 2).getImm();
4600 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
4601 : RISCV::VMSLE_VI;
4602 emitToStreamer(S&: Out, Inst: MCInstBuilder(Opc)
4603 .addOperand(Op: Inst.getOperand(i: 0))
4604 .addOperand(Op: Inst.getOperand(i: 1))
4605 .addImm(Val: Imm - 1)
4606 .addOperand(Op: Inst.getOperand(i: 3))
4607 .setLoc(IDLoc));
4608 return false;
4609 }
4610 case RISCV::PseudoVMSGEU_VI:
4611 case RISCV::PseudoVMSLTU_VI: {
4612 int64_t Imm = Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(Opc)
4622 .addOperand(Op: Inst.getOperand(i: 0))
4623 .addOperand(Op: Inst.getOperand(i: 1))
4624 .addOperand(Op: Inst.getOperand(i: 1))
4625 .addOperand(Op: Inst.getOperand(i: 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(S&: Out, Inst: MCInstBuilder(Opc)
4633 .addOperand(Op: Inst.getOperand(i: 0))
4634 .addOperand(Op: Inst.getOperand(i: 1))
4635 .addImm(Val: Imm - 1)
4636 .addOperand(Op: Inst.getOperand(i: 3))
4637 .setLoc(IDLoc));
4638 }
4639
4640 return false;
4641 }
4642 case RISCV::PseudoCV_ELW:
4643 emitLoadStoreSymbol(Inst, Opcode: RISCV::CV_ELW, IDLoc, Out, /*HasTmpReg=*/false);
4644 return false;
4645 }
4646
4647 emitToStreamer(S&: Out, Inst);
4648 return false;
4649}
4650
4651extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
4652LLVMInitializeRISCVAsmParser() {
4653 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
4654 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
4655 RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());
4656 RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());
4657}
4658