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