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