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