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