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