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