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