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