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
1413static bool regClassIsYGPR(const MCRegisterClass &RC) {
1414 assert(RC.getNumRegs() > 0);
1415 return getRISCVMCRegisterClass(RISCV::YGPRRegClassID).contains(*RC.begin());
1416}
1417
1418unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1419 unsigned Kind) {
1420 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1421 if (!Op.isReg())
1422 return Match_InvalidOperand;
1423
1424 MCRegister Reg = Op.getReg();
1425 bool IsRegFPR64 =
1426 getRISCVMCRegisterClass(RISCV::FPR64RegClassID).contains(Reg);
1427 bool IsRegFPR64C =
1428 getRISCVMCRegisterClass(RISCV::FPR64CRegClassID).contains(Reg);
1429 bool IsRegVR = getRISCVMCRegisterClass(RISCV::VRRegClassID).contains(Reg);
1430
1431 // YGPR and GPR use the same register names in assembly, so convert GPR
1432 // operands to YGPR when matching a YGPR register class (such as YGPRNoX0).
1433 if (Op.isGPR()) {
1434 const MCRegisterClass *RC =
1435 getRegClassFromMatchKind(static_cast<MatchClassKind>(Kind));
1436 if (RC && regClassIsYGPR(*RC)) {
1437 MCRegister YReg = convertGPRToYGPR(Reg);
1438 if (RC->contains(YReg)) {
1439 Op.Reg.Reg = YReg;
1440 return Match_Success;
1441 }
1442 }
1443 }
1444 if (IsRegFPR64 && Kind == MCK_FPR256) {
1445 Op.Reg.Reg = convertFPR64ToFPR256(Reg);
1446 return Match_Success;
1447 }
1448 if (IsRegFPR64 && Kind == MCK_FPR128) {
1449 Op.Reg.Reg = convertFPR64ToFPR128(Reg);
1450 return Match_Success;
1451 }
1452 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1453 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1454 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1455 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1456 Op.Reg.Reg = convertFPR64ToFPR32(Reg);
1457 return Match_Success;
1458 }
1459 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1460 // register from FPR64 to FPR16 if necessary.
1461 if (IsRegFPR64 && Kind == MCK_FPR16) {
1462 Op.Reg.Reg = convertFPR64ToFPR16(Reg);
1463 return Match_Success;
1464 }
1465 if (Kind == MCK_GPRAsFPR16 && Op.isGPRAsFPR()) {
1466 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_H;
1467 return Match_Success;
1468 }
1469 if (Kind == MCK_GPRAsFPR32 && Op.isGPRAsFPR()) {
1470 Op.Reg.Reg = Reg - RISCV::X0 + RISCV::X0_W;
1471 return Match_Success;
1472 }
1473
1474 // There are some GPRF64AsFPR instructions that have no RV32 equivalent. We
1475 // reject them at parsing thinking we should match as GPRPairAsFPR for RV32.
1476 // So we explicitly accept them here for RV32 to allow the generic code to
1477 // report that the instruction requires RV64.
1478 if (getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg) &&
1479 Kind == MCK_GPRF64AsFPR && STI->hasFeature(RISCV::FeatureStdExtZdinx) &&
1480 !isRV64())
1481 return Match_Success;
1482
1483 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1484 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1485 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1486 Op.Reg.Reg = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1487 if (!Op.Reg.Reg)
1488 return Match_InvalidOperand;
1489 return Match_Success;
1490 }
1491 return Match_InvalidOperand;
1492}
1493
1494bool RISCVAsmParser::generateImmOutOfRangeError(
1495 SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
1496 const Twine &Msg = "immediate must be an integer in the range") {
1497 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1498}
1499
1500// Some diagnostics need to vary with subtarget features, so they are handled
1501// here. For example, several immediate ranges depend on whether the target is
1502// RV32 or RV64.
1503std::string RISCVAsmParser::getCustomOperandDiag(unsigned MatchError) {
1504 auto Range = [](int64_t Lower, int64_t Upper,
1505 StringRef Msg = "immediate must be an integer in the range") {
1506 return (Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]").str();
1507 };
1508
1509 switch (MatchError) {
1510 default:
1511 // For all other operand diagnostics, use the static string generated by
1512 // TableGen from the DiagnosticString field, if any.
1513 if (const char *Diag = getMatchKindDiag((RISCVMatchResultTy)MatchError))
1514 return Diag;
1515 return std::string();
1516 case Match_InvalidImmXLenLI:
1517 if (isRV64())
1518 return "operand must be a constant 64-bit integer";
1519 return Range(std::numeric_limits<int32_t>::min(),
1520 std::numeric_limits<uint32_t>::max());
1521 case Match_InvalidImmXLenLI_Restricted:
1522 if (isRV64())
1523 return "operand either must be a constant 64-bit integer "
1524 "or a bare symbol name";
1525 return Range(std::numeric_limits<int32_t>::min(),
1526 std::numeric_limits<uint32_t>::max(),
1527 "operand either must be a bare symbol name or an immediate "
1528 "integer in the range");
1529 case Match_InvalidUImmLog2XLen:
1530 if (isRV64())
1531 return Range(0, (1 << 6) - 1);
1532 return Range(0, (1 << 5) - 1);
1533 case Match_InvalidUImmLog2XLenNonZero:
1534 if (isRV64())
1535 return Range(1, (1 << 6) - 1);
1536 return Range(1, (1 << 5) - 1);
1537 case Match_InvalidUImm1:
1538 return Range(0, (1 << 1) - 1);
1539 case Match_InvalidUImm2:
1540 return Range(0, (1 << 2) - 1);
1541 case Match_InvalidUImm2Lsb0:
1542 return Range(0, 2, "immediate must be one of");
1543 case Match_InvalidUImm3:
1544 return Range(0, (1 << 3) - 1);
1545 case Match_InvalidUImm4:
1546 return Range(0, (1 << 4) - 1);
1547 case Match_InvalidUImm4Plus1:
1548 return Range(1, (1 << 4));
1549 case Match_InvalidUImm5:
1550 return Range(0, (1 << 5) - 1);
1551 case Match_InvalidUImm5NonZero:
1552 return Range(1, (1 << 5) - 1);
1553 case Match_InvalidUImm5GT3:
1554 return Range(4, (1 << 5) - 1);
1555 case Match_InvalidUImm5Plus1:
1556 return Range(1, (1 << 5));
1557 case Match_InvalidUImm5GE6Plus1:
1558 return Range(6, (1 << 5));
1559 case Match_InvalidUImm5Slist:
1560 return "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31";
1561 case Match_InvalidUImm6:
1562 return Range(0, (1 << 6) - 1);
1563 case Match_InvalidUImm6Plus1:
1564 return Range(1, (1 << 6));
1565 case Match_InvalidUImm7:
1566 return Range(0, (1 << 7) - 1);
1567 case Match_InvalidUImm8:
1568 return Range(0, (1 << 8) - 1);
1569 case Match_InvalidUImm8GE32:
1570 return Range(32, (1 << 8) - 1);
1571 case Match_InvalidSImm5:
1572 return Range(-(1 << 4), (1 << 4) - 1);
1573 case Match_InvalidSImm5NonZero:
1574 return Range(-(1 << 4), (1 << 4) - 1,
1575 "immediate must be non-zero in the range");
1576 case Match_InvalidSImm6:
1577 return Range(-(1 << 5), (1 << 5) - 1);
1578 case Match_InvalidSImm6NonZero:
1579 return Range(-(1 << 5), (1 << 5) - 1,
1580 "immediate must be non-zero in the range");
1581 case Match_InvalidCLUIImm:
1582 return Range(1, (1 << 5) - 1, "immediate must be in [0xfffe0, 0xfffff] or");
1583 case Match_InvalidUImm5Lsb0:
1584 return Range(0, (1 << 5) - 2,
1585 "immediate must be a multiple of 2 bytes in the range");
1586 case Match_InvalidUImm6Lsb0:
1587 return Range(0, (1 << 6) - 2,
1588 "immediate must be a multiple of 2 bytes in the range");
1589 case Match_InvalidUImm6Lsb000:
1590 return Range(0, (1 << 6) - 8,
1591 "immediate must be a multiple of 8 in the range");
1592 case Match_InvalidUImm7Lsb00:
1593 return Range(0, (1 << 7) - 4,
1594 "immediate must be a multiple of 4 bytes in the range");
1595 case Match_InvalidUImm8Lsb00:
1596 return Range(0, (1 << 8) - 4,
1597 "immediate must be a multiple of 4 bytes in the range");
1598 case Match_InvalidUImm8Lsb000:
1599 return Range(0, (1 << 8) - 8,
1600 "immediate must be a multiple of 8 bytes in the range");
1601 case Match_InvalidUImm9:
1602 return Range(0, (1 << 9) - 1, "immediate offset must be in the range");
1603 case Match_InvalidBareSImm9Lsb0:
1604 return Range(-(1 << 8), (1 << 8) - 2,
1605 "immediate must be a multiple of 2 bytes in the range");
1606 case Match_InvalidUImm9Lsb000:
1607 return Range(0, (1 << 9) - 8,
1608 "immediate must be a multiple of 8 bytes in the range");
1609 case Match_InvalidSImm8PLI_B:
1610 return Range(-(1 << 7), (1 << 8) - 1);
1611 case Match_InvalidSImm10:
1612 case Match_InvalidSImm10PLI_H:
1613 case Match_InvalidSImm10PLI_W:
1614 return Range(-(1 << 9), (1 << 9) - 1);
1615 case Match_InvalidSImm10PLUI:
1616 return Range(-(1 << 9), (1 << 10) - 1);
1617 case Match_InvalidUImm10Lsb00NonZero:
1618 return Range(4, (1 << 10) - 4,
1619 "immediate must be a multiple of 4 bytes in the range");
1620 case Match_InvalidSImm10Lsb0000NonZero:
1621 return Range(
1622 -(1 << 9), (1 << 9) - 16,
1623 "immediate must be a multiple of 16 bytes and non-zero in the range");
1624 case Match_InvalidSImm11:
1625 return Range(-(1 << 10), (1 << 10) - 1);
1626 case Match_InvalidBareSImm11Lsb0:
1627 return Range(-(1 << 10), (1 << 10) - 2,
1628 "immediate must be a multiple of 2 bytes in the range");
1629 case Match_InvalidUImm10:
1630 return Range(0, (1 << 10) - 1);
1631 case Match_InvalidUImm11:
1632 return Range(0, (1 << 11) - 1);
1633 case Match_InvalidUImm14Lsb00:
1634 return Range(0, (1 << 14) - 4,
1635 "immediate must be a multiple of 4 bytes in the range");
1636 case Match_InvalidUImm16NonZero:
1637 return Range(1, (1 << 16) - 1);
1638 case Match_InvalidSImm12:
1639 return Range(-(1 << 11), (1 << 11) - 1);
1640 case Match_InvalidSImm12LO:
1641 return Range(-(1 << 11), (1 << 11) - 1,
1642 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo "
1643 "specifier or an integer in the range");
1644 case Match_InvalidBareSImm12Lsb0:
1645 return Range(-(1 << 11), (1 << 11) - 2,
1646 "immediate must be a multiple of 2 bytes in the range");
1647 case Match_InvalidSImm12Lsb00000:
1648 return Range(-(1 << 11), (1 << 11) - 32,
1649 "immediate must be a multiple of 32 bytes in the range");
1650 case Match_InvalidBareSImm13Lsb0:
1651 return Range(-(1 << 12), (1 << 12) - 2,
1652 "immediate must be a multiple of 2 bytes in the range");
1653 case Match_InvalidSImm16:
1654 return Range(-(1 << 15), (1 << 15) - 1);
1655 case Match_InvalidSImm16NonZero:
1656 return Range(-(1 << 15), (1 << 15) - 1,
1657 "immediate must be non-zero in the range");
1658 case Match_InvalidSImm20LI:
1659 return Range(-(1 << 19), (1 << 19) - 1,
1660 "operand must be a symbol with a %qc.abs20 specifier or an "
1661 "integer in the range");
1662 case Match_InvalidUImm20LUI:
1663 return Range(0, (1 << 20) - 1,
1664 "operand must be a symbol with %hi/%tprel_hi specifier or an "
1665 "integer in the range");
1666 case Match_InvalidUImm20:
1667 return Range(0, (1 << 20) - 1);
1668 case Match_InvalidUImm20AUIPC:
1669 return Range(
1670 0, (1 << 20) - 1,
1671 "operand must be a symbol with a "
1672 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi specifier "
1673 "or an integer in the range");
1674 case Match_InvalidBareSImm21Lsb0:
1675 return Range(-(1 << 20), (1 << 20) - 2,
1676 "immediate must be a multiple of 2 bytes in the range");
1677 case Match_InvalidCSRSystemRegister:
1678 return Range(0, (1 << 12) - 1,
1679 "operand must be a valid system register name or an integer "
1680 "in the range");
1681 case Match_InvalidImm5Zibi:
1682 return Range(-1, (1 << 5) - 1, "immediate must be non-zero in the range");
1683 case Match_InvalidVTypeI:
1684 return "operand must be "
1685 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]";
1686 case Match_InvalidSImm5Plus1:
1687 return Range(-(1 << 4) + 1, (1 << 4), "immediate must be in the range");
1688 case Match_InvalidSImm18:
1689 return Range(-(1 << 17), (1 << 17) - 1);
1690 case Match_InvalidSImm18Lsb0:
1691 return Range(-(1 << 17), (1 << 17) - 2,
1692 "immediate must be a multiple of 2 bytes in the range");
1693 case Match_InvalidSImm19Lsb00:
1694 return Range(-(1 << 18), (1 << 18) - 4,
1695 "immediate must be a multiple of 4 bytes in the range");
1696 case Match_InvalidSImm20Lsb000:
1697 return Range(-(1 << 19), (1 << 19) - 8,
1698 "immediate must be a multiple of 8 bytes in the range");
1699 case Match_InvalidSImm26:
1700 return Range(-(1 << 25), (1 << 25) - 1);
1701 // HACK: See comment before `BareSymbolQC_E_LI` in RISCVInstrInfoXqci.td.
1702 case Match_InvalidBareSymbolQC_E_LI:
1703 [[fallthrough]];
1704 // END HACK
1705 case Match_InvalidBareSImm32:
1706 return Range(std::numeric_limits<int32_t>::min(),
1707 std::numeric_limits<uint32_t>::max());
1708 case Match_InvalidBareSImm32Lsb0:
1709 return Range(std::numeric_limits<int32_t>::min(),
1710 std::numeric_limits<int32_t>::max() - 1,
1711 "operand must be a multiple of 2 bytes in the range");
1712 case Match_InvalidRnumArg:
1713 return Range(0, 10);
1714 case Match_InvalidStackAdj:
1715 return "stack adjustment is invalid for this instruction and register "
1716 "list";
1717 case Match_InvalidYBNDSWImm:
1718 return "immediate must be an integer in the range "
1719 "[1, 255], a multiple of 8 in the range [256, 504], "
1720 "or a multiple of 16 in the range [512, 4096]";
1721 }
1722}
1723
1724// Process the list of near-misses, throwing away ones we don't want to report
1725// to the user, and converting the rest to a source location and string that
1726// should be reported.
1727void RISCVAsmParser::FilterNearMisses(
1728 SmallVectorImpl<NearMissInfo> &NearMissesIn,
1729 SmallVectorImpl<NearMissMessage> &NearMissesOut, SMLoc IDLoc,
1731 // Record some information about near-misses that we have already seen, so
1732 // that we can avoid reporting redundant ones.
1733 std::multimap<unsigned, unsigned> OperandMissesSeen;
1734 SmallSet<FeatureBitset, 4> FeatureMissesSeen;
1735 bool ReportedTooFewOperands = false;
1736 bool ReportedTooManyOperands = false;
1737
1738 for (NearMissInfo &I : NearMissesIn) {
1739 switch (I.getKind()) {
1741 SMLoc OperandLoc =
1742 ((RISCVOperand &)*Operands[I.getOperandIndex()]).getStartLoc();
1743
1744 // When the matcher finds surplus operands, it records them as
1745 // NearMissOperand with InvalidMatchClass. We detect this and report
1746 // "unexpected extra operand" instead of "invalid operand".
1747 if (I.getOperandClass() == InvalidMatchClass) {
1748 if (!ReportedTooManyOperands) {
1749 NearMissesOut.emplace_back(NearMissMessage{
1750 OperandLoc, "unexpected extra operand for instruction"});
1751 ReportedTooManyOperands = true;
1752 }
1753 break;
1754 }
1755
1756 std::string OperandDiag = getCustomOperandDiag(I.getOperandError());
1757
1758 // If we have already emitted a message for a superclass on this operand,
1759 // don't also report the sub-class.
1760 unsigned DupCheckMatchClass =
1761 OperandDiag.empty() ? ~0U : I.getOperandClass();
1762 auto PrevReports = OperandMissesSeen.equal_range(I.getOperandIndex());
1763 if (std::any_of(
1764 PrevReports.first, PrevReports.second,
1765 [DupCheckMatchClass](const std::pair<unsigned, unsigned> Pair) {
1766 if (DupCheckMatchClass == ~0U || Pair.second == ~0U)
1767 return Pair.second == DupCheckMatchClass;
1768 return isSubclass((MatchClassKind)DupCheckMatchClass,
1769 (MatchClassKind)Pair.second);
1770 }))
1771 break;
1772 OperandMissesSeen.insert(
1773 std::make_pair(I.getOperandIndex(), DupCheckMatchClass));
1774
1775 NearMissMessage Message;
1776 Message.Loc = OperandLoc;
1777 if (!OperandDiag.empty()) {
1778 Message.Message = OperandDiag;
1779 } else {
1780 Message.Message = "invalid operand for instruction";
1781 LLVM_DEBUG(
1782 dbgs() << "Missing diagnostic string for operand class "
1783 << getMatchClassName((MatchClassKind)I.getOperandClass())
1784 << I.getOperandClass() << ", error " << I.getOperandError()
1785 << ", opcode " << MII.getName(I.getOpcode()) << "\n");
1786 }
1787 NearMissesOut.emplace_back(Message);
1788 break;
1789 }
1791 const FeatureBitset &MissingFeatures = I.getFeatures();
1792 // Don't report the same set of features twice.
1793 if (!FeatureMissesSeen.insert(MissingFeatures).second)
1794 break;
1795
1796 NearMissMessage Message;
1797 Message.Loc = IDLoc;
1798 bool FirstFeature = true;
1799 Message.Message = "instruction requires the following:";
1800 for (unsigned Feature : MissingFeatures) {
1801 Message.Message += FirstFeature ? " " : ", ";
1802 Message.Message += getSubtargetFeatureName(Feature);
1803 FirstFeature = false;
1804 }
1805 NearMissesOut.emplace_back(Message);
1806 break;
1807 }
1809 // RISC-V does not define any target match predicates.
1810 llvm_unreachable("RISC-V has no target predicate near-misses");
1811 break;
1813 if (!ReportedTooFewOperands) {
1814 SMLoc EndLoc = ((RISCVOperand &)*Operands.back()).getEndLoc();
1815 NearMissesOut.emplace_back(
1816 NearMissMessage{EndLoc, "too few operands for instruction"});
1817 ReportedTooFewOperands = true;
1818 }
1819 break;
1820 }
1822 // This should never leave the matcher.
1823 llvm_unreachable("not a near-miss");
1824 break;
1825 }
1826 }
1827}
1828
1829void RISCVAsmParser::ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses,
1830 SMLoc IDLoc, OperandVector &Operands) {
1832 FilterNearMisses(NearMisses, Messages, IDLoc, Operands);
1833
1834 if (Messages.empty()) {
1835 // No near-misses were found, so the best we can do is "invalid
1836 // instruction".
1837 Error(IDLoc, "invalid instruction");
1838 } else if (Messages.size() == 1) {
1839 // One near miss was found, report it as the sole error.
1840 Error(Messages[0].Loc, Messages[0].Message);
1841 } else {
1842 // More than one near miss, so report a generic "invalid instruction"
1843 // error, followed by notes for each of the near-misses.
1844 Error(IDLoc,
1845 "invalid instruction, any one of the following would fix this:");
1846 for (auto &M : Messages)
1847 Note(M.Loc, M.Message);
1848 }
1849}
1850
1851bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1853 MCStreamer &Out,
1854 uint64_t &ErrorInfo,
1855 bool MatchingInlineAsm) {
1856 MCInst Inst;
1858
1859 auto Result =
1860 MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm);
1861 switch (Result) {
1862 default:
1863 break;
1864 case Match_Success:
1865 if (validateInstruction(Inst, Operands))
1866 return true;
1867 return processInstruction(Inst, IDLoc, Operands, Out);
1868 case Match_MnemonicFail: {
1869 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1870 std::string Suggestion = RISCVMnemonicSpellCheck(
1871 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1872 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1873 }
1874 case Match_NearMisses:
1875 ReportNearMisses(NearMisses, IDLoc, Operands);
1876 return true;
1877 }
1878
1879 llvm_unreachable("Unknown match type detected!");
1880}
1881
1882// Attempts to match Name as a register (either using the default name or
1883// alternative ABI names), returning the matching register. Upon failure,
1884// returns a non-valid MCRegister. If IsRVE, then registers x16-x31 will be
1885// rejected.
1886MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
1887 MCRegister Reg = MatchRegisterName(Name);
1888 // The 16-/32-/128- and 64-bit FPRs have the same asm name. Check
1889 // that the initial match always matches the 64-bit variant, and
1890 // not the 16/32/128-bit one.
1891 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1892 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1893 assert(!(Reg >= RISCV::F0_Q && Reg <= RISCV::F31_Q));
1894 // The default FPR register class is based on the tablegen enum ordering.
1895 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1896 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1897 static_assert(RISCV::F0_D < RISCV::F0_Q, "FPR matching must be updated");
1898 if (!Reg)
1899 Reg = MatchRegisterAltName(Name);
1900 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1901 Reg = MCRegister();
1902 return Reg;
1903}
1904
1905bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1906 SMLoc &EndLoc) {
1907 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1908 return Error(StartLoc, "invalid register name");
1909 return false;
1910}
1911
1912ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1913 SMLoc &EndLoc) {
1914 const AsmToken &Tok = getParser().getTok();
1915 StartLoc = Tok.getLoc();
1916 EndLoc = Tok.getEndLoc();
1917 StringRef Name = getLexer().getTok().getIdentifier();
1918
1920 if (!Reg)
1921 return ParseStatus::NoMatch;
1922
1923 getParser().Lex(); // Eat identifier token.
1924 return ParseStatus::Success;
1925}
1926
1927ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1928 bool AllowParens) {
1929 SMLoc FirstS = getLoc();
1930 bool HadParens = false;
1931 AsmToken LParen;
1932
1933 // If this is an LParen and a parenthesised register name is allowed, parse it
1934 // atomically.
1935 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1936 AsmToken Buf[2];
1937 size_t ReadCount = getLexer().peekTokens(Buf);
1938 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1939 HadParens = true;
1940 LParen = getParser().getTok();
1941 getParser().Lex(); // Eat '('
1942 }
1943 }
1944
1945 switch (getLexer().getKind()) {
1946 default:
1947 if (HadParens)
1948 getLexer().UnLex(LParen);
1949 return ParseStatus::NoMatch;
1951 StringRef Name = getLexer().getTok().getIdentifier();
1952 MCRegister Reg = matchRegisterNameHelper(Name);
1953
1954 if (!Reg) {
1955 if (HadParens)
1956 getLexer().UnLex(LParen);
1957 return ParseStatus::NoMatch;
1958 }
1959 if (HadParens)
1960 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1961 SMLoc S = getLoc();
1962 SMLoc E = getTok().getEndLoc();
1963 getLexer().Lex();
1964 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
1965 }
1966
1967 if (HadParens) {
1968 getParser().Lex(); // Eat ')'
1969 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1970 }
1971
1972 return ParseStatus::Success;
1973}
1974
1975ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1976 SMLoc S = getLoc();
1977 SMLoc E;
1978 const MCExpr *Res;
1979
1980 switch (getLexer().getKind()) {
1981 default:
1982 return ParseStatus::NoMatch;
1983 case AsmToken::LParen:
1984 case AsmToken::Minus:
1985 case AsmToken::Plus:
1986 case AsmToken::Exclaim:
1987 case AsmToken::Tilde:
1988 case AsmToken::Integer:
1989 case AsmToken::String: {
1990 if (getParser().parseExpression(Res, E))
1991 return ParseStatus::Failure;
1992
1993 auto *CE = dyn_cast<MCConstantExpr>(Res);
1994 if (CE) {
1995 int64_t Imm = CE->getValue();
1996 if (isUInt<7>(Imm)) {
1997 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
1998 return ParseStatus::Success;
1999 }
2000 }
2001
2002 break;
2003 }
2004 case AsmToken::Identifier: {
2005 StringRef Identifier;
2006 if (getParser().parseIdentifier(Identifier))
2007 return ParseStatus::Failure;
2008
2009 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
2010 if (Opcode) {
2011 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
2012 "Unexpected opcode");
2013 Res = MCConstantExpr::create(Opcode->Value, getContext());
2015 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2016 return ParseStatus::Success;
2017 }
2018
2019 break;
2020 }
2021 case AsmToken::Percent:
2022 break;
2023 }
2024
2025 return generateImmOutOfRangeError(
2026 S, 0, 127,
2027 "opcode must be a valid opcode name or an immediate in the range");
2028}
2029
2030ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
2031 SMLoc S = getLoc();
2032 SMLoc E;
2033 const MCExpr *Res;
2034
2035 switch (getLexer().getKind()) {
2036 default:
2037 return ParseStatus::NoMatch;
2038 case AsmToken::LParen:
2039 case AsmToken::Minus:
2040 case AsmToken::Plus:
2041 case AsmToken::Exclaim:
2042 case AsmToken::Tilde:
2043 case AsmToken::Integer:
2044 case AsmToken::String: {
2045 if (getParser().parseExpression(Res, E))
2046 return ParseStatus::Failure;
2047
2048 auto *CE = dyn_cast<MCConstantExpr>(Res);
2049 if (CE) {
2050 int64_t Imm = CE->getValue();
2051 if (Imm >= 0 && Imm <= 2) {
2052 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2053 return ParseStatus::Success;
2054 }
2055 }
2056
2057 break;
2058 }
2059 case AsmToken::Identifier: {
2060 StringRef Identifier;
2061 if (getParser().parseIdentifier(Identifier))
2062 return ParseStatus::Failure;
2063
2064 unsigned Opcode;
2065 if (Identifier == "C0")
2066 Opcode = 0;
2067 else if (Identifier == "C1")
2068 Opcode = 1;
2069 else if (Identifier == "C2")
2070 Opcode = 2;
2071 else
2072 break;
2073
2074 Res = MCConstantExpr::create(Opcode, getContext());
2076 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2077 return ParseStatus::Success;
2078 }
2079 case AsmToken::Percent: {
2080 // Discard operand with modifier.
2081 break;
2082 }
2083 }
2084
2085 return generateImmOutOfRangeError(
2086 S, 0, 2,
2087 "opcode must be a valid opcode name or an immediate in the range");
2088}
2089
2090ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
2091 SMLoc S = getLoc();
2092 const MCExpr *Res;
2093
2094 auto SysRegFromConstantInt = [this](const MCExpr *E, SMLoc S) {
2095 if (auto *CE = dyn_cast<MCConstantExpr>(E)) {
2096 int64_t Imm = CE->getValue();
2097 if (isUInt<12>(Imm)) {
2098 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
2099 // Accept an immediate representing a named Sys Reg if it satisfies the
2100 // the required features.
2101 for (auto &Reg : Range) {
2102 if (Reg.IsAltName || Reg.IsDeprecatedName)
2103 continue;
2104 if (Reg.haveRequiredFeatures(STI->getFeatureBits()))
2105 return RISCVOperand::createSysReg(
2106 RISCVSysReg::getSysRegStr(Reg.Name), S, Imm);
2107 }
2108 // Accept an immediate representing an un-named Sys Reg if the range is
2109 // valid, regardless of the required features.
2110 return RISCVOperand::createSysReg("", S, Imm);
2111 }
2112 }
2113 return std::unique_ptr<RISCVOperand>();
2114 };
2115
2116 switch (getLexer().getKind()) {
2117 default:
2118 return ParseStatus::NoMatch;
2119 case AsmToken::LParen:
2120 case AsmToken::Minus:
2121 case AsmToken::Plus:
2122 case AsmToken::Exclaim:
2123 case AsmToken::Tilde:
2124 case AsmToken::Integer:
2125 case AsmToken::String: {
2126 if (getParser().parseExpression(Res))
2127 return ParseStatus::Failure;
2128
2129 if (auto SysOpnd = SysRegFromConstantInt(Res, S)) {
2130 Operands.push_back(std::move(SysOpnd));
2131 return ParseStatus::Success;
2132 }
2133
2134 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2135 }
2136 case AsmToken::Identifier: {
2137 StringRef Identifier;
2138 if (getParser().parseIdentifier(Identifier))
2139 return ParseStatus::Failure;
2140
2141 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
2142
2143 if (SysReg) {
2144 if (SysReg->IsDeprecatedName) {
2145 // Lookup the undeprecated name.
2146 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);
2147 for (auto &Reg : Range) {
2148 if (Reg.IsAltName || Reg.IsDeprecatedName)
2149 continue;
2150 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
2151 RISCVSysReg::getSysRegStr(Reg.Name) + "'");
2152 }
2153 }
2154
2155 // Accept a named Sys Reg if the required features are present.
2156 const auto &FeatureBits = getSTI().getFeatureBits();
2157 const auto &AllFeatures = getSTI().getAllProcessorFeatures();
2158 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
2159 const auto *Feature =
2160 llvm::find_if(AllFeatures, [&](const auto &Feature) {
2161 return SysReg->FeaturesRequired[Feature.Value];
2162 });
2163 std::string ErrorMsg =
2164 std::string("system register '") +
2165 std::string(RISCVSysReg::getSysRegStr(SysReg->Name)) + "' ";
2166 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
2167 ErrorMsg += "is RV32 only";
2168 if (Feature != std::end(AllFeatures))
2169 ErrorMsg += " and ";
2170 }
2171 if (Feature != std::end(AllFeatures)) {
2172 ErrorMsg +=
2173 "requires '" + std::string(Feature->key()) + "' to be enabled";
2174 }
2175
2176 return Error(S, ErrorMsg);
2177 }
2178 Operands.push_back(
2179 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
2180 return ParseStatus::Success;
2181 }
2182
2183 // Accept a symbol name that evaluates to an absolute value.
2184 MCSymbol *Sym = getContext().lookupSymbol(Identifier);
2185 if (Sym && Sym->isVariable()) {
2186 // Pass false for SetUsed, since redefining the value later does not
2187 // affect this instruction.
2188 if (auto SysOpnd = SysRegFromConstantInt(Sym->getVariableValue(), S)) {
2189 Operands.push_back(std::move(SysOpnd));
2190 return ParseStatus::Success;
2191 }
2192 }
2193
2194 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2195 "operand must be a valid system register "
2196 "name or an integer in the range");
2197 }
2198 case AsmToken::Percent: {
2199 // Discard operand with modifier.
2200 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2201 }
2202 }
2203
2204 return ParseStatus::NoMatch;
2205}
2206
2207ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
2208 SMLoc S = getLoc();
2209
2210 // Parse special floats (inf/nan/min) representation.
2211 if (getTok().is(AsmToken::Identifier)) {
2212 StringRef Identifier = getTok().getIdentifier();
2213 if (Identifier.compare_insensitive("inf") == 0) {
2214 Operands.push_back(
2215 RISCVOperand::createExpr(MCConstantExpr::create(30, getContext()), S,
2216 getTok().getEndLoc(), isRV64()));
2217 } else if (Identifier.compare_insensitive("nan") == 0) {
2218 Operands.push_back(
2219 RISCVOperand::createExpr(MCConstantExpr::create(31, getContext()), S,
2220 getTok().getEndLoc(), isRV64()));
2221 } else if (Identifier.compare_insensitive("min") == 0) {
2222 Operands.push_back(
2223 RISCVOperand::createExpr(MCConstantExpr::create(1, getContext()), S,
2224 getTok().getEndLoc(), isRV64()));
2225 } else {
2226 return TokError("invalid floating point literal");
2227 }
2228
2229 Lex(); // Eat the token.
2230
2231 return ParseStatus::Success;
2232 }
2233
2234 // Handle negation, as that still comes through as a separate token.
2235 bool IsNegative = parseOptionalToken(AsmToken::Minus);
2236
2237 const AsmToken &Tok = getTok();
2238 if (!Tok.is(AsmToken::Real))
2239 return TokError("invalid floating point immediate");
2240
2241 // Parse FP representation.
2242 APFloat RealVal(APFloat::IEEEdouble());
2243 auto StatusOrErr =
2244 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2245 if (errorToBool(StatusOrErr.takeError()))
2246 return TokError("invalid floating point representation");
2247
2248 if (IsNegative)
2249 RealVal.changeSign();
2250
2251 Operands.push_back(RISCVOperand::createFPImm(
2252 RealVal.bitcastToAPInt().getZExtValue(), S));
2253
2254 Lex(); // Eat the token.
2255
2256 return ParseStatus::Success;
2257}
2258
2259ParseStatus RISCVAsmParser::parseExpression(OperandVector &Operands) {
2260 SMLoc S = getLoc();
2261 SMLoc E;
2262 const MCExpr *Res;
2263
2264 switch (getLexer().getKind()) {
2265 default:
2266 return ParseStatus::NoMatch;
2267 case AsmToken::LParen:
2268 case AsmToken::Dot:
2269 case AsmToken::Minus:
2270 case AsmToken::Plus:
2271 case AsmToken::Exclaim:
2272 case AsmToken::Tilde:
2273 case AsmToken::Integer:
2274 case AsmToken::String:
2276 if (getParser().parseExpression(Res, E))
2277 return ParseStatus::Failure;
2278 break;
2279 case AsmToken::Percent:
2280 return parseOperandWithSpecifier(Operands);
2281 }
2282
2283 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2284 return ParseStatus::Success;
2285}
2286
2287ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
2288 SMLoc S = getLoc();
2289 SMLoc E;
2290
2291 if (parseToken(AsmToken::Percent, "expected '%' relocation specifier"))
2292 return ParseStatus::Failure;
2293 const MCExpr *Expr = nullptr;
2294 bool Failed = parseExprWithSpecifier(Expr, E);
2295 if (!Failed)
2296 Operands.push_back(RISCVOperand::createExpr(Expr, S, E, isRV64()));
2297 return Failed;
2298}
2299
2300bool RISCVAsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
2301 SMLoc Loc = getLoc();
2302 if (getLexer().getKind() != AsmToken::Identifier)
2303 return TokError("expected '%' relocation specifier");
2304 StringRef Identifier = getParser().getTok().getIdentifier();
2305 auto Spec = RISCV::parseSpecifierName(Identifier);
2306 if (!Spec)
2307 return TokError("invalid relocation specifier");
2308
2309 getParser().Lex(); // Eat the identifier
2310 if (parseToken(AsmToken::LParen, "expected '('"))
2311 return true;
2312
2313 const MCExpr *SubExpr;
2314 if (getParser().parseParenExpression(SubExpr, E))
2315 return true;
2316
2317 Res = MCSpecifierExpr::create(SubExpr, Spec, getContext(), Loc);
2318 return false;
2319}
2320
2321bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {
2322 SMLoc E;
2323 if (parseOptionalToken(AsmToken::Percent))
2324 return parseExprWithSpecifier(Res, E);
2325 return getParser().parseExpression(Res);
2326}
2327
2328ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
2329 SMLoc S = getLoc();
2330 const MCExpr *Res;
2331
2332 if (getLexer().getKind() != AsmToken::Identifier)
2333 return ParseStatus::NoMatch;
2334
2335 StringRef Identifier = getTok().getIdentifier();
2336 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2337
2338 if (Sym->isVariable()) {
2339 const MCExpr *V = Sym->getVariableValue();
2340 if (!isa<MCSymbolRefExpr>(V))
2341 return ParseStatus::NoMatch;
2342 }
2343
2344 SMLoc E;
2345 if (getParser().parseExpression(Res, E))
2346 return ParseStatus::Failure;
2347
2348 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2349 return ParseStatus::Success;
2350}
2351
2352ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2353 SMLoc S = getLoc();
2354 const MCExpr *Res;
2355
2356 if (getLexer().getKind() != AsmToken::Identifier)
2357 return ParseStatus::NoMatch;
2358 std::string Identifier(getTok().getIdentifier());
2359
2360 if (getLexer().peekTok().is(AsmToken::At)) {
2361 Lex();
2362 Lex();
2363 StringRef PLT;
2364 SMLoc Loc = getLoc();
2365 if (getParser().parseIdentifier(PLT) || PLT != "plt")
2366 return Error(Loc, "@ (except the deprecated/ignored @plt) is disallowed");
2367 } else if (!getLexer().peekTok().is(AsmToken::EndOfStatement)) {
2368 // Avoid parsing the register in `call rd, foo` as a call symbol.
2369 return ParseStatus::NoMatch;
2370 } else {
2371 Lex();
2372 }
2373
2374 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
2376
2377 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2378 Res = MCSymbolRefExpr::create(Sym, getContext());
2379 Res = MCSpecifierExpr::create(Res, Kind, getContext());
2380 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2381 return ParseStatus::Success;
2382}
2383
2384// Like parseCallSymbol but allows the symbol to be followed by a comma
2385// (for "tail address, register" form where the symbol is not the last operand).
2386ParseStatus RISCVAsmParser::parseTailCallSymbol(OperandVector &Operands) {
2387 SMLoc S = getLoc();
2388 const MCExpr *Res;
2389
2390 if (getLexer().getKind() != AsmToken::Identifier)
2391 return ParseStatus::NoMatch;
2392 std::string Identifier(getTok().getIdentifier());
2393
2394 if (getLexer().peekTok().is(AsmToken::At)) {
2395 Lex();
2396 Lex();
2397 StringRef PLT;
2398 SMLoc Loc = getLoc();
2399 if (getParser().parseIdentifier(PLT) || PLT != "plt")
2400 return Error(Loc, "@ (except the deprecated/ignored @plt) is disallowed");
2401 } else if (!getLexer().peekTok().is(AsmToken::EndOfStatement) &&
2402 !getLexer().peekTok().is(AsmToken::Comma)) {
2403 return ParseStatus::NoMatch;
2404 } else {
2405 Lex();
2406 }
2407
2408 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
2410
2411 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2412 Res = MCSymbolRefExpr::create(Sym, getContext());
2413 Res = MCSpecifierExpr::create(Res, Kind, getContext());
2414 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2415 return ParseStatus::Success;
2416}
2417
2418ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2419 SMLoc S = getLoc();
2420 SMLoc E;
2421 const MCExpr *Res;
2422
2423 if (getParser().parseExpression(Res, E))
2424 return ParseStatus::Failure;
2425
2426 if (Res->getKind() != MCExpr::ExprKind::SymbolRef)
2427 return Error(S, "operand must be a valid jump target");
2428
2430 Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
2431 return ParseStatus::Success;
2432}
2433
2434ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2435 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2436 // both being acceptable forms. When parsing `jal ra, foo` this function
2437 // will be called for the `ra` register operand in an attempt to match the
2438 // single-operand alias. parseJALOffset must fail for this case. It would
2439 // seem logical to try parse the operand using parseExpression and return
2440 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2441 // the second form rather than the first). We can't do this as there's no
2442 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2443 // is an identifier and is followed by a comma.
2444 if (getLexer().is(AsmToken::Identifier) &&
2445 getLexer().peekTok().is(AsmToken::Comma))
2446 return ParseStatus::NoMatch;
2447
2448 return parseExpression(Operands);
2449}
2450
2451bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
2452 unsigned &Sew, unsigned &Lmul,
2453 bool &Fractional, bool &TailAgnostic,
2454 bool &MaskAgnostic, bool &AltFmt) {
2455 if (Tok.isNot(AsmToken::Identifier))
2456 return true;
2457
2458 StringRef Identifier = Tok.getIdentifier();
2459 if (State < VTypeState::SeenSew && Identifier.consume_front("e")) {
2460 if (Identifier.getAsInteger(10, Sew)) {
2461 if (Identifier == "16alt") {
2462 AltFmt = true;
2463 Sew = 16;
2464 } else if (Identifier == "8alt") {
2465 AltFmt = true;
2466 Sew = 8;
2467 } else {
2468 return true;
2469 }
2470 }
2471 if (!RISCVVType::isValidSEW(Sew))
2472 return true;
2473
2474 State = VTypeState::SeenSew;
2475 return false;
2476 }
2477
2478 if (State < VTypeState::SeenLmul && Identifier.consume_front("m")) {
2479 // Might arrive here if lmul and tail policy unspecified, if so we're
2480 // parsing a MaskPolicy not an LMUL.
2481 if (Identifier == "a" || Identifier == "u") {
2482 MaskAgnostic = (Identifier == "a");
2483 State = VTypeState::SeenMaskPolicy;
2484 return false;
2485 }
2486
2487 Fractional = Identifier.consume_front("f");
2488 if (Identifier.getAsInteger(10, Lmul))
2489 return true;
2490 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2491 return true;
2492
2493 if (Fractional) {
2494 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2495 unsigned MinLMUL = ELEN / 8;
2496 if (Lmul > MinLMUL)
2497 Warning(Tok.getLoc(),
2498 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2499 Twine(MinLMUL) + " is reserved");
2500 }
2501
2502 State = VTypeState::SeenLmul;
2503 return false;
2504 }
2505
2506 if (State < VTypeState::SeenTailPolicy && Identifier.starts_with("t")) {
2507 if (Identifier == "ta")
2508 TailAgnostic = true;
2509 else if (Identifier == "tu")
2510 TailAgnostic = false;
2511 else
2512 return true;
2513
2514 State = VTypeState::SeenTailPolicy;
2515 return false;
2516 }
2517
2518 if (State < VTypeState::SeenMaskPolicy && Identifier.starts_with("m")) {
2519 if (Identifier == "ma")
2520 MaskAgnostic = true;
2521 else if (Identifier == "mu")
2522 MaskAgnostic = false;
2523 else
2524 return true;
2525
2526 State = VTypeState::SeenMaskPolicy;
2527 return false;
2528 }
2529
2530 return true;
2531}
2532
2533ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2534 SMLoc S = getLoc();
2535
2536 // Default values
2537 unsigned Sew = 8;
2538 unsigned Lmul = 1;
2539 bool Fractional = false;
2540 bool TailAgnostic = false;
2541 bool MaskAgnostic = false;
2542 bool AltFmt = false;
2543
2544 VTypeState State = VTypeState::SeenNothingYet;
2545 do {
2546 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2547 MaskAgnostic, AltFmt)) {
2548 // The first time, errors return NoMatch rather than Failure
2549 if (State == VTypeState::SeenNothingYet)
2550 return ParseStatus::NoMatch;
2551 break;
2552 }
2553
2554 getLexer().Lex();
2555 } while (parseOptionalToken(AsmToken::Comma));
2556
2557 if (!getLexer().is(AsmToken::EndOfStatement) ||
2558 State == VTypeState::SeenNothingYet)
2559 return generateVTypeError(S);
2560
2562 if (Fractional) {
2563 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2564 unsigned MaxSEW = ELEN / Lmul;
2565 // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2566 if (MaxSEW >= 8 && Sew > MaxSEW)
2567 Warning(S, "use of vtype encodings with SEW > " + Twine(MaxSEW) +
2568 " and LMUL == mf" + Twine(Lmul) +
2569 " may not be compatible with all RVV implementations");
2570 }
2571
2572 unsigned VTypeI =
2573 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic, AltFmt);
2574 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2575 return ParseStatus::Success;
2576}
2577
2578bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2579 return Error(ErrorLoc,
2580 "operand must be "
2581 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2582}
2583
2584ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
2585 SMLoc S = getLoc();
2586
2587 unsigned Widen = 0;
2588 unsigned SEW = 0;
2589 bool AltFmt = false;
2590 StringRef Identifier;
2591
2592 if (getTok().isNot(AsmToken::Identifier))
2593 goto Fail;
2594
2595 Identifier = getTok().getIdentifier();
2596
2597 if (!Identifier.consume_front("e"))
2598 goto Fail;
2599
2600 if (Identifier.getAsInteger(10, SEW)) {
2601 if (Identifier != "16alt")
2602 goto Fail;
2603
2604 AltFmt = true;
2605 SEW = 16;
2606 }
2607 if (!RISCVVType::isValidSEW(SEW))
2608 goto Fail;
2609
2610 Lex();
2611
2612 if (!parseOptionalToken(AsmToken::Comma))
2613 goto Fail;
2614
2615 if (getTok().isNot(AsmToken::Identifier))
2616 goto Fail;
2617
2618 Identifier = getTok().getIdentifier();
2619
2620 if (!Identifier.consume_front("w"))
2621 goto Fail;
2622 if (Identifier.getAsInteger(10, Widen))
2623 goto Fail;
2624 if (Widen != 1 && Widen != 2 && Widen != 4)
2625 goto Fail;
2626
2627 Lex();
2628
2629 if (getLexer().is(AsmToken::EndOfStatement)) {
2630 Operands.push_back(RISCVOperand::createVType(
2631 RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
2632 return ParseStatus::Success;
2633 }
2634
2635Fail:
2636 return generateXSfmmVTypeError(S);
2637}
2638
2639bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
2640 return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");
2641}
2642
2643ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2644 if (getLexer().isNot(AsmToken::Identifier))
2645 return ParseStatus::NoMatch;
2646
2647 StringRef Name = getLexer().getTok().getIdentifier();
2648 if (!Name.consume_back(".t")) {
2649 // Non-register identifiers may belong to another optional operand in an
2650 // overloaded mnemonic. Let the matcher try those alternatives.
2651 if (matchRegisterNameHelper(Name))
2652 return Error(getLoc(), "expected '.t' suffix");
2653 return ParseStatus::NoMatch;
2654 }
2655 MCRegister Reg = matchRegisterNameHelper(Name);
2656
2657 if (!Reg)
2658 return ParseStatus::NoMatch;
2659 if (Reg != RISCV::V0)
2660 return ParseStatus::NoMatch;
2661 SMLoc S = getLoc();
2662 SMLoc E = getTok().getEndLoc();
2663 getLexer().Lex();
2664 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2665 return ParseStatus::Success;
2666}
2667
2668ParseStatus RISCVAsmParser::parseVScaleReg(OperandVector &Operands) {
2669 if (getLexer().isNot(AsmToken::Identifier))
2670 return ParseStatus::NoMatch;
2671
2672 StringRef Name = getLexer().getTok().getIdentifier();
2673 if (!Name.consume_back(".scale"))
2674 return Error(getLoc(), "expected '.scale' suffix");
2675 MCRegister Reg = matchRegisterNameHelper(Name);
2676
2677 if (!Reg)
2678 return ParseStatus::NoMatch;
2679 if (Reg != RISCV::V0)
2680 return ParseStatus::NoMatch;
2681 SMLoc S = getLoc();
2682 SMLoc E = getTok().getEndLoc();
2683 getLexer().Lex();
2684 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2685 return ParseStatus::Success;
2686}
2687
2688ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
2689 if (getLexer().isNot(AsmToken::Identifier))
2690 return ParseStatus::NoMatch;
2691
2692 SMLoc S = getLoc();
2693 StringRef Name = getLexer().getTok().getIdentifier();
2694 if (!Name.consume_front("L") && !Name.consume_front("l"))
2695 return ParseStatus::NoMatch;
2696
2697 unsigned Lambda;
2698 if (Name.getAsInteger(10, Lambda) || !isPowerOf2_32(Lambda) || Lambda >= 128)
2699 return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
2700
2701 unsigned EncodedLambda = Log2_32(Lambda) + 1;
2702
2703 SMLoc E = getTok().getEndLoc();
2704 getLexer().Lex();
2705 Operands.push_back(RISCVOperand::createExpr(
2706 MCConstantExpr::create(EncodedLambda, getContext()), S, E, isRV64()));
2707 return ParseStatus::Success;
2708}
2709
2710ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
2711 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2712 return ParseStatus::NoMatch;
2713
2714 return parseGPRAsFPR(Operands);
2715}
2716
2717ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2718 if (getLexer().isNot(AsmToken::Identifier))
2719 return ParseStatus::NoMatch;
2720
2721 StringRef Name = getLexer().getTok().getIdentifier();
2722 MCRegister Reg = matchRegisterNameHelper(Name);
2723
2724 if (!Reg)
2725 return ParseStatus::NoMatch;
2726 SMLoc S = getLoc();
2727 SMLoc E = getTok().getEndLoc();
2728 getLexer().Lex();
2729 Operands.push_back(RISCVOperand::createReg(
2730 Reg, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2731 return ParseStatus::Success;
2732}
2733
2734ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
2735 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2736 return ParseStatus::NoMatch;
2737
2738 if (getLexer().isNot(AsmToken::Identifier))
2739 return ParseStatus::NoMatch;
2740
2741 StringRef Name = getLexer().getTok().getIdentifier();
2742 MCRegister Reg = matchRegisterNameHelper(Name);
2743
2744 if (!Reg)
2745 return ParseStatus::NoMatch;
2746
2747 if (!getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg))
2748 return ParseStatus::NoMatch;
2749
2750 if ((Reg - RISCV::X0) & 1) {
2751 // Only report the even register error if we have at least Zfinx so we know
2752 // some FP is enabled. We already checked F earlier.
2753 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2754 return TokError("double precision floating point operands must use even "
2755 "numbered X register");
2756 return ParseStatus::NoMatch;
2757 }
2758
2759 SMLoc S = getLoc();
2760 SMLoc E = getTok().getEndLoc();
2761 getLexer().Lex();
2762
2763 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2764 MCRegister Pair = RI->getMatchingSuperReg(
2765 Reg, RISCV::sub_gpr_even,
2766 &getRISCVMCRegisterClass(RISCV::GPRPairRegClassID));
2767 Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));
2768 return ParseStatus::Success;
2769}
2770
2771template <bool IsRV64>
2772ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2773 return parseGPRPair(Operands, IsRV64);
2774}
2775
2776ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2777 bool IsRV64Inst) {
2778 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2779 // RV64 as it will prevent matching the RV64 version of the same instruction
2780 // that doesn't use a GPRPair.
2781 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2782 // still parse as a pair.
2783 if (!IsRV64Inst && isRV64())
2784 return ParseStatus::NoMatch;
2785
2786 if (getLexer().isNot(AsmToken::Identifier))
2787 return ParseStatus::NoMatch;
2788
2789 StringRef Name = getLexer().getTok().getIdentifier();
2790 MCRegister Reg = matchRegisterNameHelper(Name);
2791
2792 if (!Reg)
2793 return ParseStatus::NoMatch;
2794
2795 if (!getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(Reg))
2796 return ParseStatus::NoMatch;
2797
2798 if ((Reg - RISCV::X0) & 1)
2799 return TokError("register must be even");
2800
2801 SMLoc S = getLoc();
2802 SMLoc E = getTok().getEndLoc();
2803 getLexer().Lex();
2804
2805 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2806 MCRegister Pair = RI->getMatchingSuperReg(
2807 Reg, RISCV::sub_gpr_even,
2808 &getRISCVMCRegisterClass(RISCV::GPRPairRegClassID));
2809 Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2810 return ParseStatus::Success;
2811}
2812
2813ParseStatus RISCVAsmParser::parseSMTVType(OperandVector &Operands) {
2814 if (getLexer().isNot(AsmToken::Identifier))
2815 return TokError(
2816 "operand must be a valid SpacemiT's Integer Matrix VType mnemonic");
2817
2818 StringRef Str = getLexer().getTok().getIdentifier();
2820
2821 if (!isValidSMTVTypeMode(VType))
2822 return TokError("SpacemiT's Integer Matrix only supports [i4|i8] mode");
2823
2824 Operands.push_back(RISCVOperand::createSMTVType(VType, getLoc()));
2825 Lex(); // Eat identifier token.
2826 return ParseStatus::Success;
2827}
2828
2829ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2830 if (getLexer().isNot(AsmToken::Identifier))
2831 return TokError(
2832 "operand must be a valid floating point rounding mode mnemonic");
2833
2834 StringRef Str = getLexer().getTok().getIdentifier();
2836
2837 if (FRM == RISCVFPRndMode::Invalid)
2838 return TokError(
2839 "operand must be a valid floating point rounding mode mnemonic");
2840
2841 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2842 Lex(); // Eat identifier token.
2843 return ParseStatus::Success;
2844}
2845
2846std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultSMTVType() {
2847 return RISCVOperand::createSMTVType(XSMTVTypeMode::SMTVTypeMode::SMT_I8,
2848 SMLoc());
2849}
2850
2851ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2852 const AsmToken &Tok = getLexer().getTok();
2853
2854 if (Tok.is(AsmToken::Integer)) {
2855 if (Tok.getIntVal() != 0)
2856 goto ParseFail;
2857
2858 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2859 Lex();
2860 return ParseStatus::Success;
2861 }
2862
2863 if (Tok.is(AsmToken::Identifier)) {
2864 StringRef Str = Tok.getIdentifier();
2865
2866 // Letters must be unique, taken from 'iorw', and in ascending order. This
2867 // holds as long as each individual character is one of 'iorw' and is
2868 // greater than the previous character.
2869 unsigned Imm = 0;
2870 bool Valid = true;
2871 char Prev = '\0';
2872 for (char c : Str) {
2873 switch (c) {
2874 default:
2875 Valid = false;
2876 break;
2877 case 'i':
2879 break;
2880 case 'o':
2882 break;
2883 case 'r':
2885 break;
2886 case 'w':
2888 break;
2889 }
2890
2891 if (c <= Prev) {
2892 Valid = false;
2893 break;
2894 }
2895 Prev = c;
2896 }
2897
2898 if (!Valid)
2899 goto ParseFail;
2900
2901 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2902 Lex();
2903 return ParseStatus::Success;
2904 }
2905
2906ParseFail:
2907 return TokError("operand must be formed of letters selected in-order from "
2908 "'iorw' or be 0");
2909}
2910
2911ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2912 if (parseToken(AsmToken::LParen, "expected '('"))
2913 return ParseStatus::Failure;
2914 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2915
2916 if (!parseRegister(Operands).isSuccess())
2917 return Error(getLoc(), "expected register");
2918
2919 if (parseToken(AsmToken::RParen, "expected ')'"))
2920 return ParseStatus::Failure;
2921 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2922
2923 return ParseStatus::Success;
2924}
2925
2926ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2927 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2928 // as one of their register operands, such as `(a0)`. This just denotes that
2929 // the register (in this case `a0`) contains a memory address.
2930 //
2931 // Normally, we would be able to parse these by putting the parens into the
2932 // instruction string. However, GNU as also accepts a zero-offset memory
2933 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2934 // with parseExpression followed by parseMemOpBaseReg, but these instructions
2935 // do not accept an immediate operand, and we do not want to add a "dummy"
2936 // operand that is silently dropped.
2937 //
2938 // Instead, we use this custom parser. This will: allow (and discard) an
2939 // offset if it is zero; require (and discard) parentheses; and add only the
2940 // parsed register operand to `Operands`.
2941 //
2942 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2943 // which will only print the register surrounded by parentheses (which GNU as
2944 // also uses as its canonical representation for these operands).
2945 std::unique_ptr<RISCVOperand> OptionalImmOp;
2946
2947 if (getLexer().isNot(AsmToken::LParen)) {
2948 // Parse an Integer token. We do not accept arbitrary constant expressions
2949 // in the offset field (because they may include parens, which complicates
2950 // parsing a lot).
2951 int64_t ImmVal;
2952 SMLoc ImmStart = getLoc();
2953 if (getParser().parseIntToken(ImmVal,
2954 "expected '(' or optional integer offset"))
2955 return ParseStatus::Failure;
2956
2957 // Create a RISCVOperand for checking later (so the error messages are
2958 // nicer), but we don't add it to Operands.
2959 SMLoc ImmEnd = getLoc();
2960 OptionalImmOp =
2961 RISCVOperand::createExpr(MCConstantExpr::create(ImmVal, getContext()),
2962 ImmStart, ImmEnd, isRV64());
2963 }
2964
2965 if (parseToken(AsmToken::LParen,
2966 OptionalImmOp ? "expected '(' after optional integer offset"
2967 : "expected '(' or optional integer offset"))
2968 return ParseStatus::Failure;
2969
2970 if (!parseRegister(Operands).isSuccess())
2971 return Error(getLoc(), "expected register");
2972
2973 if (parseToken(AsmToken::RParen, "expected ')'"))
2974 return ParseStatus::Failure;
2975
2976 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2977 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2978 return Error(
2979 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2980 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2981
2982 return ParseStatus::Success;
2983}
2984
2985ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2986 // RR : a2(a1)
2987 if (getLexer().getKind() != AsmToken::Identifier)
2988 return ParseStatus::NoMatch;
2989
2990 SMLoc S = getLoc();
2991 StringRef OffsetRegName = getLexer().getTok().getIdentifier();
2992 MCRegister OffsetReg = matchRegisterNameHelper(OffsetRegName);
2993 if (!OffsetReg ||
2994 !getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(OffsetReg))
2995 return Error(getLoc(), "expected GPR register");
2996 getLexer().Lex();
2997
2998 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
2999 return ParseStatus::Failure;
3000
3001 if (getLexer().getKind() != AsmToken::Identifier)
3002 return Error(getLoc(), "expected GPR register");
3003
3004 StringRef BaseRegName = getLexer().getTok().getIdentifier();
3005 MCRegister BaseReg = matchRegisterNameHelper(BaseRegName);
3006 if (!BaseReg ||
3007 !getRISCVMCRegisterClass(RISCV::GPRRegClassID).contains(BaseReg))
3008 return Error(getLoc(), "expected GPR register");
3009 getLexer().Lex();
3010
3011 if (parseToken(AsmToken::RParen, "expected ')'"))
3012 return ParseStatus::Failure;
3013
3014 Operands.push_back(RISCVOperand::createRegReg(BaseReg, OffsetReg, S));
3015
3016 return ParseStatus::Success;
3017}
3018
3019// RegList: {ra [, s0[-sN]]}
3020// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
3021
3022// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
3023// must include `fp`/`s0` in the list:
3024// RegList: {ra, s0[-sN]}
3025// XRegList: {x1, x8[-x9][, x18[-xN]]}
3026ParseStatus RISCVAsmParser::parseRegList(OperandVector &Operands,
3027 bool MustIncludeS0) {
3028 if (getTok().isNot(AsmToken::LCurly))
3029 return ParseStatus::NoMatch;
3030
3031 SMLoc S = getLoc();
3032
3033 Lex();
3034
3035 bool UsesXRegs;
3036 MCRegister RegEnd;
3037 do {
3038 if (getTok().isNot(AsmToken::Identifier))
3039 return Error(getLoc(), "invalid register");
3040
3041 StringRef RegName = getTok().getIdentifier();
3042 MCRegister Reg = matchRegisterNameHelper(RegName);
3043 if (!Reg)
3044 return Error(getLoc(), "invalid register");
3045
3046 if (!RegEnd) {
3047 UsesXRegs = RegName[0] == 'x';
3048 if (Reg != RISCV::X1)
3049 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
3050 } else if (RegEnd == RISCV::X1) {
3051 if (Reg != RISCV::X8 || (UsesXRegs != (RegName[0] == 'x')))
3052 return Error(getLoc(), Twine("register must be '") +
3053 (UsesXRegs ? "x8" : "s0") + "'");
3054 } else if (RegEnd == RISCV::X9 && UsesXRegs) {
3055 if (Reg != RISCV::X18 || (RegName[0] != 'x'))
3056 return Error(getLoc(), "register must be 'x18'");
3057 } else {
3058 return Error(getLoc(), "too many register ranges");
3059 }
3060
3061 RegEnd = Reg;
3062
3063 Lex();
3064
3065 SMLoc MinusLoc = getLoc();
3066 if (parseOptionalToken(AsmToken::Minus)) {
3067 if (RegEnd == RISCV::X1)
3068 return Error(MinusLoc, Twine("register '") + (UsesXRegs ? "x1" : "ra") +
3069 "' cannot start a multiple register range");
3070
3071 if (getTok().isNot(AsmToken::Identifier))
3072 return Error(getLoc(), "invalid register");
3073
3074 StringRef RegName = getTok().getIdentifier();
3075 MCRegister Reg = matchRegisterNameHelper(RegName);
3076 if (!Reg)
3077 return Error(getLoc(), "invalid register");
3078
3079 if (RegEnd == RISCV::X8) {
3080 if ((Reg != RISCV::X9 &&
3081 (UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||
3082 (UsesXRegs != (RegName[0] == 'x'))) {
3083 if (UsesXRegs)
3084 return Error(getLoc(), "register must be 'x9'");
3085 return Error(getLoc(), "register must be in the range 's1' to 's11'");
3086 }
3087 } else if (RegEnd == RISCV::X18) {
3088 if (Reg < RISCV::X19 || Reg > RISCV::X27 || (RegName[0] != 'x'))
3089 return Error(getLoc(),
3090 "register must be in the range 'x19' to 'x27'");
3091 } else
3092 llvm_unreachable("unexpected register");
3093
3094 RegEnd = Reg;
3095
3096 Lex();
3097 }
3098 } while (parseOptionalToken(AsmToken::Comma));
3099
3100 if (parseToken(AsmToken::RCurly, "expected ',' or '}'"))
3101 return ParseStatus::Failure;
3102
3103 if (RegEnd == RISCV::X26)
3104 return Error(S, "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
3105 "x18-x26}' is not supported");
3106
3107 auto Encode = RISCVZC::encodeRegList(RegEnd, isRVE());
3108 assert(Encode != RISCVZC::INVALID_RLIST);
3109
3110 if (MustIncludeS0 && Encode == RISCVZC::RA)
3111 return Error(S, "register list must include 's0' or 'x8'");
3112
3113 Operands.push_back(RISCVOperand::createRegList(Encode, S));
3114
3115 return ParseStatus::Success;
3116}
3117
3118ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
3119 bool ExpectNegative) {
3120 SMLoc S = getLoc();
3121 bool Negative = parseOptionalToken(AsmToken::Minus);
3122
3123 if (getTok().isNot(AsmToken::Integer))
3124 return ParseStatus::NoMatch;
3125
3126 int64_t StackAdjustment = getTok().getIntVal();
3127
3128 auto *RegListOp = static_cast<RISCVOperand *>(Operands.back().get());
3129 if (!RegListOp->isRegList())
3130 return ParseStatus::NoMatch;
3131
3132 unsigned RlistEncode = RegListOp->RegList.Encoding;
3133
3134 assert(RlistEncode != RISCVZC::INVALID_RLIST);
3135 unsigned StackAdjBase = RISCVZC::getStackAdjBase(RlistEncode, isRV64());
3136 if (Negative != ExpectNegative || StackAdjustment % 16 != 0 ||
3137 StackAdjustment < StackAdjBase || (StackAdjustment - StackAdjBase) > 48) {
3138 int64_t Lower = StackAdjBase;
3139 int64_t Upper = StackAdjBase + 48;
3140 if (ExpectNegative) {
3141 Lower = -Lower;
3142 Upper = -Upper;
3144 }
3145 return generateImmOutOfRangeError(S, Lower, Upper,
3146 "stack adjustment for register list must "
3147 "be a multiple of 16 bytes in the range");
3148 }
3149
3150 unsigned StackAdj = (StackAdjustment - StackAdjBase);
3151 Operands.push_back(RISCVOperand::createStackAdj(StackAdj, S));
3152 Lex();
3153 return ParseStatus::Success;
3154}
3155
3156/// Looks at a token type and creates the relevant operand from this
3157/// information, adding to Operands. If operand was parsed, returns false, else
3158/// true.
3159bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
3160 // Check if the current operand has a custom associated parser, if so, try to
3161 // custom parse the operand, or fallback to the general approach.
3162 ParseStatus Result =
3163 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
3164 if (Result.isSuccess())
3165 return false;
3166 if (Result.isFailure())
3167 return true;
3168
3169 // Attempt to parse token as a register.
3170 if (parseRegister(Operands, true).isSuccess())
3171 return false;
3172
3173 // Attempt to parse token as an expression
3174 if (parseExpression(Operands).isSuccess()) {
3175 // Parse memory base register if present
3176 if (getLexer().is(AsmToken::LParen))
3177 return !parseMemOpBaseReg(Operands).isSuccess();
3178 return false;
3179 }
3180
3181 // Finally we have exhausted all options and must declare defeat.
3182 Error(getLoc(), "unknown operand");
3183 return true;
3184}
3185
3186bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,
3187 StringRef Name, SMLoc NameLoc,
3189 // Apply mnemonic aliases because the destination mnemonic may have require
3190 // custom operand parsing. The generic tblgen'erated code does this later, at
3191 // the start of MatchInstructionImpl(), but that's too late for custom
3192 // operand parsing.
3193 const FeatureBitset &AvailableFeatures = getAvailableFeatures();
3194 applyMnemonicAliases(Name, AvailableFeatures, 0);
3195
3196 // First operand is token for instruction
3197 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
3198
3199 // If there are no more operands, then finish
3200 if (getLexer().is(AsmToken::EndOfStatement)) {
3201 getParser().Lex(); // Consume the EndOfStatement.
3202 return false;
3203 }
3204
3205 // Parse first operand
3206 if (parseOperand(Operands, Name))
3207 return true;
3208
3209 // Parse until end of statement, consuming commas between operands
3210 while (parseOptionalToken(AsmToken::Comma)) {
3211 // Parse next operand
3212 if (parseOperand(Operands, Name))
3213 return true;
3214 }
3215
3216 if (getParser().parseEOL("unexpected token")) {
3217 getParser().eatToEndOfStatement();
3218 return true;
3219 }
3220 return false;
3221}
3222
3223bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
3224 RISCV::Specifier &Kind) {
3226 if (const auto *RE = dyn_cast<MCSpecifierExpr>(Expr)) {
3227 Kind = RE->getSpecifier();
3228 Expr = RE->getSubExpr();
3229 }
3230
3231 MCValue Res;
3232 if (Expr->evaluateAsRelocatable(Res, nullptr))
3233 return Res.getSpecifier() == RISCV::S_None;
3234 return false;
3235}
3236
3237bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
3238 MCValue Res;
3239 if (Expr->evaluateAsRelocatable(Res, nullptr)) {
3240 return Res.getSpecifier() == RISCV::S_None && Res.getAddSym() &&
3241 Res.getSubSym();
3242 }
3243 return false;
3244}
3245
3246ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
3247 StringRef IDVal = DirectiveID.getString();
3248
3249 if (IDVal == ".option")
3250 return parseDirectiveOption();
3251 if (IDVal == ".attribute")
3252 return parseDirectiveAttribute();
3253 if (IDVal == ".insn")
3254 return parseDirectiveInsn(DirectiveID.getLoc());
3255 if (IDVal == ".variant_cc")
3256 return parseDirectiveVariantCC();
3257
3258 return ParseStatus::NoMatch;
3259}
3260
3261bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
3262 bool FromOptionDirective) {
3263 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
3264 Arch, /*EnableExperimentalExtension=*/true,
3265 /*ExperimentalExtensionVersionCheck=*/true);
3266 if (!ParseResult) {
3267 std::string Buffer;
3268 raw_string_ostream OutputErrMsg(Buffer);
3269 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
3270 OutputErrMsg << "invalid arch name '" << Arch << "', "
3271 << ErrMsg.getMessage();
3272 });
3273
3274 return Error(Loc, OutputErrMsg.str());
3275 }
3276 auto &ISAInfo = *ParseResult;
3277
3278 if (FromOptionDirective) {
3279 if (ISAInfo->getXLen() == 32 && isRV64())
3280 return Error(Loc, "bad arch string switching from rv64 to rv32");
3281 else if (ISAInfo->getXLen() == 64 && !isRV64())
3282 return Error(Loc, "bad arch string switching from rv32 to rv64");
3283 }
3284 if (ISAInfo->getXLen() != 32 && ISAInfo->getXLen() != 64)
3285 return Error(Loc, "bad arch string " + Arch);
3286
3287 // RISCVISAInfo::parseArchString already expands all implied extensions
3288 // (including conditional C/Zce implications like Zcd and Zcf), so we can
3289 // toggle the feature bits directly without calling setFeatureBits() (which
3290 // would run updateCZceFeatureImplications() on an incomplete feature set).
3291 MCSubtargetInfo &STI = copySTI();
3292 for (auto &Feature : STI.getAllProcessorFeatures()) {
3294 continue;
3295 if (ISAInfo->hasExtension(Feature.key()) != STI.hasFeature(Feature.Value))
3296 STI.ToggleFeature(Feature.Value);
3297 }
3298 if ((ISAInfo->getXLen() == 64) != STI.hasFeature(RISCV::Feature64Bit))
3299 STI.ToggleFeature(RISCV::Feature64Bit);
3300 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
3301
3302 Result = ISAInfo->toString();
3303 return false;
3304}
3305
3306bool RISCVAsmParser::parseDirectiveOption() {
3307 MCAsmParser &Parser = getParser();
3308 // Get the option token.
3309 AsmToken Tok = Parser.getTok();
3310
3311 // At the moment only identifiers are supported.
3312 if (parseToken(AsmToken::Identifier, "expected identifier"))
3313 return true;
3314
3315 StringRef Option = Tok.getIdentifier();
3316
3317 if (Option == "push") {
3318 if (Parser.parseEOL())
3319 return true;
3320
3321 getTargetStreamer().emitDirectiveOptionPush();
3322 pushFeatureBits();
3323 return false;
3324 }
3325
3326 if (Option == "pop") {
3327 SMLoc StartLoc = Parser.getTok().getLoc();
3328 if (Parser.parseEOL())
3329 return true;
3330
3331 getTargetStreamer().emitDirectiveOptionPop();
3332 if (popFeatureBits())
3333 return Error(StartLoc, ".option pop with no .option push");
3334
3335 return false;
3336 }
3337
3338 if (Option == "arch") {
3340 do {
3341 if (Parser.parseComma())
3342 return true;
3343
3345 if (parseOptionalToken(AsmToken::Plus))
3346 Type = RISCVOptionArchArgType::Plus;
3347 else if (parseOptionalToken(AsmToken::Minus))
3348 Type = RISCVOptionArchArgType::Minus;
3349 else if (!Args.empty())
3350 return Error(Parser.getTok().getLoc(),
3351 "unexpected token, expected + or -");
3352 else
3353 Type = RISCVOptionArchArgType::Full;
3354
3355 if (Parser.getTok().isNot(AsmToken::Identifier))
3356 return Error(Parser.getTok().getLoc(),
3357 "unexpected token, expected identifier");
3358
3359 StringRef Arch = Parser.getTok().getString();
3360 SMLoc Loc = Parser.getTok().getLoc();
3361 Parser.Lex();
3362
3363 if (Type == RISCVOptionArchArgType::Full) {
3364 std::string Result;
3365 if (resetToArch(Arch, Loc, Result, true))
3366 return true;
3367
3368 Args.emplace_back(Type, Result);
3369 break;
3370 }
3371
3372 if (isDigit(Arch.back()))
3373 return Error(
3374 Loc, "extension version number parsing not currently implemented");
3375
3376 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
3377 if (!enableExperimentalExtension() &&
3378 StringRef(Feature).starts_with("experimental-"))
3379 return Error(Loc, "unexpected experimental extensions");
3380 const auto &AllFeatures = getSTI().getAllProcessorFeatures();
3381 auto Ext = llvm::lower_bound(AllFeatures, Feature);
3382 if (Ext == std::end(AllFeatures) || StringRef(Ext->key()) != Feature)
3383 return Error(Loc, "unknown extension feature");
3384
3385 if (Ext->Value == RISCV::FeatureStdExtY)
3386 return Error(Loc, "passing '+y'/'-y' is not supported yet; specify a "
3387 "full arch string instead");
3388
3389 Args.emplace_back(Type, Arch.str());
3390
3391 if (Type == RISCVOptionArchArgType::Plus) {
3392 FeatureBitset OldFeatureBits = STI->getFeatureBits();
3393
3394 setFeatureBits(Ext->Value, Ext->key());
3395 auto ParseResult = RISCVFeatures::parseFeatureBits(*STI);
3396 if (!ParseResult) {
3397 copySTI().setFeatureBits(OldFeatureBits);
3398 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3399
3400 std::string Buffer;
3401 raw_string_ostream OutputErrMsg(Buffer);
3402 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
3403 OutputErrMsg << ErrMsg.getMessage();
3404 });
3405
3406 return Error(Loc, OutputErrMsg.str());
3407 }
3408 } else {
3409 assert(Type == RISCVOptionArchArgType::Minus);
3410 // It is invalid to disable an extension that there are other enabled
3411 // extensions depend on it.
3412 // TODO: Make use of RISCVISAInfo to handle this
3413 for (auto &Feature : AllFeatures) {
3414 if (getSTI().hasFeature(Feature.Value) &&
3415 Feature.Implies.test(Ext->Value))
3416 return Error(Loc, Twine("can't disable ") + Ext->key() +
3417 " extension; " + Feature.key() +
3418 " extension requires " + Ext->key() +
3419 " extension");
3420 }
3421
3422 clearFeatureBits(Ext->Value, Ext->key());
3423 }
3424 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
3425
3426 if (Parser.parseEOL())
3427 return true;
3428
3429 getTargetStreamer().emitDirectiveOptionArch(Args);
3430
3431 if (auto ParseResult = RISCVFeatures::parseFeatureBits(*STI))
3432 getTargetStreamer().setArchString((*ParseResult)->toString());
3433 return false;
3434 }
3435
3436 if (Option == "exact") {
3437 if (Parser.parseEOL())
3438 return true;
3439
3440 getTargetStreamer().emitDirectiveOptionExact();
3441 setFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
3442 clearFeatureBits(RISCV::FeatureRelax, "relax");
3443 return false;
3444 }
3445
3446 if (Option == "noexact") {
3447 if (Parser.parseEOL())
3448 return true;
3449
3450 getTargetStreamer().emitDirectiveOptionNoExact();
3451 clearFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
3452 setFeatureBits(RISCV::FeatureRelax, "relax");
3453 return false;
3454 }
3455
3456 if (Option == "rvc") {
3457 if (Parser.parseEOL())
3458 return true;
3459
3460 getTargetStreamer().emitDirectiveOptionRVC();
3461 setFeatureBits(RISCV::FeatureStdExtC, "c");
3462 if (auto ParseResult = RISCVFeatures::parseFeatureBits(*STI))
3463 getTargetStreamer().setArchString((*ParseResult)->toString());
3464 return false;
3465 }
3466
3467 if (Option == "norvc") {
3468 if (Parser.parseEOL())
3469 return true;
3470
3471 getTargetStreamer().emitDirectiveOptionNoRVC();
3472 clearFeatureBits(RISCV::FeatureStdExtC, "c");
3473 clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
3474 if (auto ParseResult = RISCVFeatures::parseFeatureBits(*STI))
3475 getTargetStreamer().setArchString((*ParseResult)->toString());
3476 return false;
3477 }
3478
3479 if (Option == "pic") {
3480 if (Parser.parseEOL())
3481 return true;
3482
3483 getTargetStreamer().emitDirectiveOptionPIC();
3484 ParserOptions.IsPicEnabled = true;
3485 return false;
3486 }
3487
3488 if (Option == "nopic") {
3489 if (Parser.parseEOL())
3490 return true;
3491
3492 getTargetStreamer().emitDirectiveOptionNoPIC();
3493 ParserOptions.IsPicEnabled = false;
3494 return false;
3495 }
3496
3497 if (Option == "relax") {
3498 if (Parser.parseEOL())
3499 return true;
3500
3501 getTargetStreamer().emitDirectiveOptionRelax();
3502 setFeatureBits(RISCV::FeatureRelax, "relax");
3503 return false;
3504 }
3505
3506 if (Option == "norelax") {
3507 if (Parser.parseEOL())
3508 return true;
3509
3510 getTargetStreamer().emitDirectiveOptionNoRelax();
3511 clearFeatureBits(RISCV::FeatureRelax, "relax");
3512 return false;
3513 }
3514
3515 // Unknown option.
3516 Warning(Parser.getTok().getLoc(),
3517 "unknown option, expected 'push', 'pop', "
3518 "'rvc', 'norvc', 'arch', 'relax', 'norelax', "
3519 "'exact', or 'noexact'");
3520 Parser.eatToEndOfStatement();
3521 return false;
3522}
3523
3524/// parseDirectiveAttribute
3525/// ::= .attribute expression ',' ( expression | "string" )
3526/// ::= .attribute identifier ',' ( expression | "string" )
3527bool RISCVAsmParser::parseDirectiveAttribute() {
3528 MCAsmParser &Parser = getParser();
3529 int64_t Tag;
3530 SMLoc TagLoc;
3531 TagLoc = Parser.getTok().getLoc();
3532 if (Parser.getTok().is(AsmToken::Identifier)) {
3533 StringRef Name = Parser.getTok().getIdentifier();
3534 std::optional<unsigned> Ret =
3536 if (!Ret)
3537 return Error(TagLoc, "attribute name not recognised: " + Name);
3538 Tag = *Ret;
3539 Parser.Lex();
3540 } else {
3541 const MCExpr *AttrExpr;
3542
3543 TagLoc = Parser.getTok().getLoc();
3544 if (Parser.parseExpression(AttrExpr))
3545 return true;
3546
3547 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
3548 if (check(!CE, TagLoc, "expected numeric constant"))
3549 return true;
3550
3551 Tag = CE->getValue();
3552 }
3553
3554 if (Parser.parseComma())
3555 return true;
3556
3557 StringRef StringValue;
3558 int64_t IntegerValue = 0;
3559 bool IsIntegerValue = true;
3560
3561 // RISC-V attributes have a string value if the tag number is odd
3562 // and an integer value if the tag number is even.
3563 if (Tag % 2)
3564 IsIntegerValue = false;
3565
3566 SMLoc ValueExprLoc = Parser.getTok().getLoc();
3567 if (IsIntegerValue) {
3568 const MCExpr *ValueExpr;
3569 if (Parser.parseExpression(ValueExpr))
3570 return true;
3571
3572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
3573 if (!CE)
3574 return Error(ValueExprLoc, "expected numeric constant");
3575 IntegerValue = CE->getValue();
3576 } else {
3577 if (Parser.getTok().isNot(AsmToken::String))
3578 return Error(Parser.getTok().getLoc(), "expected string constant");
3579
3580 StringValue = Parser.getTok().getStringContents();
3581 Parser.Lex();
3582 }
3583
3584 if (Parser.parseEOL())
3585 return true;
3586
3587 if (IsIntegerValue)
3588 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3589 else if (Tag != RISCVAttrs::ARCH)
3590 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3591 else {
3592 std::string Result;
3593 if (resetToArch(StringValue, ValueExprLoc, Result, false))
3594 return true;
3595
3596 // Then emit the arch string.
3597 getTargetStreamer().emitTextAttribute(Tag, Result);
3598
3599 // And then update the active ISA so the next instruction-run emits
3600 // an ISA-specific mapping symbol.
3601 getTargetStreamer().setArchString(Result);
3602 }
3603
3604 return false;
3605}
3606
3608 return StringSwitch<bool>(Format)
3609 .Cases({"r", "r4", "i", "b", "sb", "u", "j", "uj", "s"}, true)
3610 .Cases({"cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj"},
3611 STI.hasFeature(RISCV::FeatureStdExtZca))
3612 .Cases({"qc.eai", "qc.ei", "qc.eb", "qc.ej", "qc.es"},
3613 !STI.hasFeature(RISCV::Feature64Bit))
3614 .Default(false);
3615}
3616
3617/// parseDirectiveInsn
3618/// ::= .insn [ format encoding, (operands (, operands)*) ]
3619/// ::= .insn [ length, value ]
3620/// ::= .insn [ value ]
3621bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3622 MCAsmParser &Parser = getParser();
3623
3624 // Expect instruction format as identifier.
3625 StringRef Format;
3626 SMLoc ErrorLoc = Parser.getTok().getLoc();
3627 if (Parser.parseIdentifier(Format)) {
3628 // Try parsing .insn [ length , ] value
3629 std::optional<int64_t> Length;
3630 int64_t Value = 0;
3631 if (Parser.parseAbsoluteExpression(Value))
3632 return true;
3633 if (Parser.parseOptionalToken(AsmToken::Comma)) {
3634 Length = Value;
3635 if (Parser.parseAbsoluteExpression(Value))
3636 return true;
3637
3638 if (*Length == 0 || (*Length % 2) != 0)
3639 return Error(ErrorLoc,
3640 "instruction lengths must be a non-zero multiple of two");
3641
3642 // TODO: Support Instructions > 64 bits.
3643 if (*Length > 8)
3644 return Error(ErrorLoc,
3645 "instruction lengths over 64 bits are not supported");
3646 }
3647
3648 // We only derive a length from the encoding for 16- and 32-bit
3649 // instructions, as the encodings for longer instructions are not frozen in
3650 // the spec.
3651 int64_t EncodingDerivedLength = ((Value & 0b11) == 0b11) ? 4 : 2;
3652
3653 if (Length) {
3654 // Only check the length against the encoding if the length is present and
3655 // could match
3656 if ((*Length <= 4) && (*Length != EncodingDerivedLength))
3657 return Error(ErrorLoc,
3658 "instruction length does not match the encoding");
3659
3660 if (!isUIntN(*Length * 8, Value))
3661 return Error(ErrorLoc, "encoding value does not fit into instruction");
3662 } else {
3663 if (!isUIntN(EncodingDerivedLength * 8, Value))
3664 return Error(ErrorLoc, "encoding value does not fit into instruction");
3665 }
3666
3667 if (!getSTI().hasFeature(RISCV::FeatureStdExtZca) &&
3668 (EncodingDerivedLength == 2))
3669 return Error(ErrorLoc, "compressed instructions are not allowed");
3670
3671 if (getParser().parseEOL("invalid operand for instruction")) {
3672 getParser().eatToEndOfStatement();
3673 return true;
3674 }
3675
3676 unsigned Opcode;
3677 if (Length) {
3678 switch (*Length) {
3679 case 2:
3680 Opcode = RISCV::Insn16;
3681 break;
3682 case 4:
3683 Opcode = RISCV::Insn32;
3684 break;
3685 case 6:
3686 Opcode = RISCV::Insn48;
3687 break;
3688 case 8:
3689 Opcode = RISCV::Insn64;
3690 break;
3691 default:
3692 llvm_unreachable("Error should have already been emitted");
3693 }
3694 } else
3695 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3696
3697 emitToStreamer(getStreamer(), MCInstBuilder(Opcode).addImm(Value));
3698 return false;
3699 }
3700
3701 if (!isValidInsnFormat(Format, getSTI()))
3702 return Error(ErrorLoc, "invalid instruction format");
3703
3704 std::string FormatName = (".insn_" + Format).str();
3705
3706 ParseInstructionInfo Info;
3708
3709 if (parseInstruction(Info, FormatName, L, Operands))
3710 return true;
3711
3712 unsigned Opcode;
3713 uint64_t ErrorInfo;
3714 return matchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3715 ErrorInfo,
3716 /*MatchingInlineAsm=*/false);
3717}
3718
3719/// parseDirectiveVariantCC
3720/// ::= .variant_cc symbol
3721bool RISCVAsmParser::parseDirectiveVariantCC() {
3722 StringRef Name;
3723 if (getParser().parseIdentifier(Name))
3724 return TokError("expected symbol name");
3725 if (parseEOL())
3726 return true;
3727 getTargetStreamer().emitDirectiveVariantCC(
3728 *getContext().getOrCreateSymbol(Name));
3729 return false;
3730}
3731
3732void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3733 MCInst CInst;
3734 bool Res = false;
3735 const MCSubtargetInfo &STI = getSTI();
3736 if (!STI.hasFeature(RISCV::FeatureExactAssembly))
3737 Res = RISCVRVC::compress(CInst, Inst, STI);
3738 if (Res)
3739 ++RISCVNumInstrsCompressed;
3740 S.emitInstruction((Res ? CInst : Inst), STI);
3741}
3742
3743void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3744 MCStreamer &Out) {
3746 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
3747
3748 for (MCInst &Inst : Seq) {
3749 emitToStreamer(Out, Inst);
3750 }
3751}
3752
3753void RISCVAsmParser::emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,
3754 const MCExpr *Symbol,
3755 RISCV::Specifier VKHi,
3756 unsigned SecondOpcode, SMLoc IDLoc,
3757 MCStreamer &Out) {
3758 // A pair of instructions for PC-relative addressing; expands to
3759 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3760 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3761 MCContext &Ctx = getContext();
3762
3763 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3764 Out.emitLabel(TmpLabel);
3765
3766 const auto *SymbolHi = MCSpecifierExpr::create(Symbol, VKHi, Ctx);
3767 emitToStreamer(Out,
3768 MCInstBuilder(RISCV::AUIPC).addReg(TmpReg).addExpr(SymbolHi));
3769
3770 const MCExpr *RefToLinkTmpLabel = MCSpecifierExpr::create(
3771 MCSymbolRefExpr::create(TmpLabel, Ctx), RISCV::S_PCREL_LO, Ctx);
3772
3773 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3774 .addReg(DestReg)
3775 .addReg(TmpReg)
3776 .addExpr(RefToLinkTmpLabel));
3777}
3778
3779void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3780 MCStreamer &Out) {
3781 // The load local address pseudo-instruction "lla" is used in PC-relative
3782 // addressing of local symbols:
3783 // lla rdest, symbol
3784 // expands to
3785 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3786 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3787 MCRegister DestReg = Inst.getOperand(0).getReg();
3788 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3789 if (STI->hasFeature(RISCV::Feature32Bit) &&
3790 STI->hasFeature(RISCV::FeatureVendorXqcili) &&
3791 !ParserOptions.IsPicEnabled)
3792 emitToStreamer(
3793 Out, MCInstBuilder(RISCV::QC_E_LI).addReg(DestReg).addExpr(Symbol));
3794 else
3795 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCV::S_PCREL_HI, RISCV::ADDI,
3796 IDLoc, Out);
3797}
3798
3799void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3800 MCStreamer &Out) {
3801 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3802 // addressing of global symbols:
3803 // lga rdest, symbol
3804 // expands to
3805 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3806 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3807 MCRegister DestReg = Inst.getOperand(0).getReg();
3808 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3809 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3810 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCV::S_GOT_HI, SecondOpcode,
3811 IDLoc, Out);
3812}
3813
3814void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3815 MCStreamer &Out) {
3816 // The load address pseudo-instruction "la" is used in PC-relative and
3817 // GOT-indirect addressing of global symbols:
3818 // la rdest, symbol
3819 // is an alias for either (for non-PIC)
3820 // lla rdest, symbol
3821 // or (for PIC)
3822 // lga rdest, symbol
3823 if (ParserOptions.IsPicEnabled)
3824 emitLoadGlobalAddress(Inst, IDLoc, Out);
3825 else
3826 emitLoadLocalAddress(Inst, IDLoc, Out);
3827}
3828
3829void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3830 MCStreamer &Out) {
3831 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3832 // initial-exec TLS model addressing of global symbols:
3833 // la.tls.ie rdest, symbol
3834 // expands to
3835 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3836 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3837 MCRegister DestReg = Inst.getOperand(0).getReg();
3838 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3839 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3840 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GOT_HI20,
3841 SecondOpcode, IDLoc, Out);
3842}
3843
3844void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3845 MCStreamer &Out) {
3846 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3847 // global-dynamic TLS model addressing of global symbols:
3848 // la.tls.gd rdest, symbol
3849 // expands to
3850 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3851 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3852 MCRegister DestReg = Inst.getOperand(0).getReg();
3853 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3854 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GD_HI20,
3855 RISCV::ADDI, IDLoc, Out);
3856}
3857
3858void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3859 SMLoc IDLoc, MCStreamer &Out,
3860 bool HasTmpReg) {
3861 // The load/store pseudo-instruction does a pc-relative load with
3862 // a symbol.
3863 //
3864 // The expansion looks like this
3865 //
3866 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3867 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3868 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3869 MCRegister DestReg = Inst.getOperand(DestRegOpIdx).getReg();
3870 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3871 MCRegister TmpReg = Inst.getOperand(0).getReg();
3872
3873 // If TmpReg is a GPR pair, get the even register.
3874 if (getRISCVMCRegisterClass(RISCV::GPRPairRegClassID).contains(TmpReg)) {
3875 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3876 TmpReg = RI->getSubReg(TmpReg, RISCV::sub_gpr_even);
3877 }
3878
3879 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3880 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCV::S_PCREL_HI, Opcode, IDLoc,
3881 Out);
3882}
3883
3884void RISCVAsmParser::emitQCELILoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3885 SMLoc IDLoc, MCStreamer &Out,
3886 bool HasTmpReg) {
3887 // For loads (HasTmpReg=false): operands are [rd, symbol]
3888 // qc.e.li rd, symbol
3889 // lx rd, 0(rd), %qc.access(symbol) [possibly compressed]
3890 //
3891 // For stores (HasTmpReg=true): operands are [rt, rs, symbol]
3892 // qc.e.li rt, symbol
3893 // sx rs, 0(rt), %qc.access(symbol) [possibly compressed]
3894 MCRegister AddrReg = Inst.getOperand(0).getReg();
3895 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3896 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3897
3898 emitToStreamer(Out,
3899 MCInstBuilder(RISCV::QC_E_LI).addReg(AddrReg).addExpr(Symbol));
3900
3901 MCContext &Ctx = getContext();
3902 const MCExpr *AccessExpr =
3904
3905 // We have to manually compress the QCAccess pseudos as the current
3906 // CompressPat mechanism does not support them. Each entry pairs the
3907 // compressed opcode with the subtarget feature it requires.
3908 struct CompressedForm {
3909 unsigned Opcode;
3910 unsigned Feature;
3911 };
3912 std::optional<CompressedForm> Compressed;
3913 switch (Opcode) {
3914 default:
3915 break;
3916 case RISCV::PseudoQCAccessLBU:
3917 Compressed = {RISCV::PseudoQCAccessC_LBU, RISCV::FeatureStdExtZcb};
3918 break;
3919 case RISCV::PseudoQCAccessLH:
3920 Compressed = {RISCV::PseudoQCAccessC_LH, RISCV::FeatureStdExtZcb};
3921 break;
3922 case RISCV::PseudoQCAccessLHU:
3923 Compressed = {RISCV::PseudoQCAccessC_LHU, RISCV::FeatureStdExtZcb};
3924 break;
3925 case RISCV::PseudoQCAccessLW:
3926 Compressed = {RISCV::PseudoQCAccessC_LW, RISCV::FeatureStdExtZca};
3927 break;
3928 case RISCV::PseudoQCAccessSB:
3929 Compressed = {RISCV::PseudoQCAccessC_SB, RISCV::FeatureStdExtZcb};
3930 break;
3931 case RISCV::PseudoQCAccessSH:
3932 Compressed = {RISCV::PseudoQCAccessC_SH, RISCV::FeatureStdExtZcb};
3933 break;
3934 case RISCV::PseudoQCAccessSW:
3935 Compressed = {RISCV::PseudoQCAccessC_SW, RISCV::FeatureStdExtZca};
3936 break;
3937 }
3938
3939 // For stores, both the data register and the address register must be in
3940 // GPRC for the compressed form; for loads AddrReg serves as both.
3941 bool CanUseGPRC =
3942 getRISCVMCRegisterClass(RISCV::GPRCRegClassID).contains(AddrReg);
3943 if (HasTmpReg && CanUseGPRC) {
3944 MCRegister DataReg = Inst.getOperand(1).getReg();
3945 CanUseGPRC =
3946 getRISCVMCRegisterClass(RISCV::GPRCRegClassID).contains(DataReg);
3947 }
3948
3949 bool UseCompressed =
3950 Compressed && getSTI().hasFeature(Compressed->Feature) && CanUseGPRC;
3951
3952 unsigned ActualOpcode = UseCompressed ? Compressed->Opcode : Opcode;
3953 if (HasTmpReg) {
3954 MCRegister DataReg = Inst.getOperand(1).getReg();
3955 emitToStreamer(Out, MCInstBuilder(ActualOpcode)
3956 .addReg(DataReg)
3957 .addReg(AddrReg)
3958 .addImm(0)
3959 .addExpr(AccessExpr));
3960 } else {
3961 emitToStreamer(Out, MCInstBuilder(ActualOpcode)
3962 .addReg(AddrReg)
3963 .addReg(AddrReg)
3964 .addImm(0)
3965 .addExpr(AccessExpr));
3966 }
3967}
3968
3969void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3970 int64_t Width, SMLoc IDLoc,
3971 MCStreamer &Out) {
3972 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3973 // amounts dependent on the XLEN.
3974 //
3975 // The expansion looks like this
3976 //
3977 // SLLI rd, rs, XLEN - Width
3978 // SR[A|R]I rd, rd, XLEN - Width
3979 const MCOperand &DestReg = Inst.getOperand(0);
3980 const MCOperand &SourceReg = Inst.getOperand(1);
3981
3982 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3983 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3984
3985 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3986
3987 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3988 .addOperand(DestReg)
3989 .addOperand(SourceReg)
3990 .addImm(ShAmt));
3991
3992 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3993 .addOperand(DestReg)
3994 .addOperand(DestReg)
3995 .addImm(ShAmt));
3996}
3997
3998void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3999 MCStreamer &Out) {
4000 if (Inst.getNumOperands() == 4 && !Inst.getOperand(3).getReg()) {
4001 // unmasked va >= x
4002 //
4003 // pseudoinstruction: vmsge{u}.vx vd, va, x
4004 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
4005 emitToStreamer(Out, MCInstBuilder(Opcode)
4006 .addOperand(Inst.getOperand(0))
4007 .addOperand(Inst.getOperand(1))
4008 .addOperand(Inst.getOperand(2))
4009 .addReg(MCRegister())
4010 .setLoc(IDLoc));
4011 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
4012 .addOperand(Inst.getOperand(0))
4013 .addOperand(Inst.getOperand(0))
4014 .addOperand(Inst.getOperand(0))
4015 .setLoc(IDLoc));
4016 } else if (Inst.getNumOperands() == 4) {
4017 // masked va >= x, vd != v0
4018 //
4019 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
4020 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
4021 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
4022 "The destination register should not be V0.");
4023 assert(Inst.getOperand(3).getReg() == RISCV::V0 && "Expected a mask");
4024 emitToStreamer(Out, MCInstBuilder(Opcode)
4025 .addOperand(Inst.getOperand(0))
4026 .addOperand(Inst.getOperand(1))
4027 .addOperand(Inst.getOperand(2))
4028 .addOperand(Inst.getOperand(3))
4029 .setLoc(IDLoc));
4030 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
4031 .addOperand(Inst.getOperand(0))
4032 .addOperand(Inst.getOperand(0))
4033 .addReg(RISCV::V0)
4034 .setLoc(IDLoc));
4035 } else if (Inst.getNumOperands() == 5 &&
4036 Inst.getOperand(0).getReg() == RISCV::V0) {
4037 // masked va >= x, vd == v0
4038 //
4039 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
4040 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
4041 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
4042 "The temporary vector register should not be V0.");
4043 emitToStreamer(Out, MCInstBuilder(Opcode)
4044 .addOperand(Inst.getOperand(1))
4045 .addOperand(Inst.getOperand(2))
4046 .addOperand(Inst.getOperand(3))
4047 .addReg(MCRegister())
4048 .setLoc(IDLoc));
4049 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
4050 .addOperand(Inst.getOperand(0))
4051 .addOperand(Inst.getOperand(0))
4052 .addOperand(Inst.getOperand(1))
4053 .setLoc(IDLoc));
4054 } else if (Inst.getNumOperands() == 5) {
4055 // masked va >= x, any vd
4056 //
4057 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
4058 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
4059 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
4060 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
4061 "The temporary vector register should not be V0.");
4062 emitToStreamer(Out, MCInstBuilder(Opcode)
4063 .addOperand(Inst.getOperand(1))
4064 .addOperand(Inst.getOperand(2))
4065 .addOperand(Inst.getOperand(3))
4066 .addReg(MCRegister())
4067 .setLoc(IDLoc));
4068 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
4069 .addOperand(Inst.getOperand(1))
4070 .addReg(RISCV::V0)
4071 .addOperand(Inst.getOperand(1))
4072 .setLoc(IDLoc));
4073 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
4074 .addOperand(Inst.getOperand(0))
4075 .addOperand(Inst.getOperand(0))
4076 .addReg(RISCV::V0)
4077 .setLoc(IDLoc));
4078 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
4079 .addOperand(Inst.getOperand(0))
4080 .addOperand(Inst.getOperand(1))
4081 .addOperand(Inst.getOperand(0))
4082 .setLoc(IDLoc));
4083 }
4084}
4085
4086bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
4088 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
4089 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
4090 if (Inst.getOperand(2).getReg() != RISCV::X4) {
4091 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
4092 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
4093 "%tprel_add specifier");
4094 }
4095
4096 return false;
4097}
4098
4099bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
4101 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
4102 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
4103 if (Inst.getOperand(0).getReg() != RISCV::X5) {
4104 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
4105 return Error(ErrorLoc, "the output operand must be t0/x5 when using "
4106 "%tlsdesc_call specifier");
4107 }
4108
4109 return false;
4110}
4111
4112std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
4113 return RISCVOperand::createReg(MCRegister(), llvm::SMLoc(), llvm::SMLoc());
4114}
4115
4116std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
4117 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
4118 llvm::SMLoc());
4119}
4120
4121std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
4122 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
4123 llvm::SMLoc());
4124}
4125
4126std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultZeroOffset() {
4127 return RISCVOperand::createExpr(MCConstantExpr::create(0, getContext()),
4128 llvm::SMLoc(), llvm::SMLoc(), isRV64());
4129}
4130
4131static unsigned getNFforLXSEG(unsigned Opcode) {
4132 switch (Opcode) {
4133 default:
4134 return 1;
4135 case RISCV::VLOXSEG2EI8_V:
4136 case RISCV::VLOXSEG2EI16_V:
4137 case RISCV::VLOXSEG2EI32_V:
4138 case RISCV::VLOXSEG2EI64_V:
4139 case RISCV::VLUXSEG2EI8_V:
4140 case RISCV::VLUXSEG2EI16_V:
4141 case RISCV::VLUXSEG2EI32_V:
4142 case RISCV::VLUXSEG2EI64_V:
4143 return 2;
4144 case RISCV::VLOXSEG3EI8_V:
4145 case RISCV::VLOXSEG3EI16_V:
4146 case RISCV::VLOXSEG3EI32_V:
4147 case RISCV::VLOXSEG3EI64_V:
4148 case RISCV::VLUXSEG3EI8_V:
4149 case RISCV::VLUXSEG3EI16_V:
4150 case RISCV::VLUXSEG3EI32_V:
4151 case RISCV::VLUXSEG3EI64_V:
4152 return 3;
4153 case RISCV::VLOXSEG4EI8_V:
4154 case RISCV::VLOXSEG4EI16_V:
4155 case RISCV::VLOXSEG4EI32_V:
4156 case RISCV::VLOXSEG4EI64_V:
4157 case RISCV::VLUXSEG4EI8_V:
4158 case RISCV::VLUXSEG4EI16_V:
4159 case RISCV::VLUXSEG4EI32_V:
4160 case RISCV::VLUXSEG4EI64_V:
4161 return 4;
4162 case RISCV::VLOXSEG5EI8_V:
4163 case RISCV::VLOXSEG5EI16_V:
4164 case RISCV::VLOXSEG5EI32_V:
4165 case RISCV::VLOXSEG5EI64_V:
4166 case RISCV::VLUXSEG5EI8_V:
4167 case RISCV::VLUXSEG5EI16_V:
4168 case RISCV::VLUXSEG5EI32_V:
4169 case RISCV::VLUXSEG5EI64_V:
4170 return 5;
4171 case RISCV::VLOXSEG6EI8_V:
4172 case RISCV::VLOXSEG6EI16_V:
4173 case RISCV::VLOXSEG6EI32_V:
4174 case RISCV::VLOXSEG6EI64_V:
4175 case RISCV::VLUXSEG6EI8_V:
4176 case RISCV::VLUXSEG6EI16_V:
4177 case RISCV::VLUXSEG6EI32_V:
4178 case RISCV::VLUXSEG6EI64_V:
4179 return 6;
4180 case RISCV::VLOXSEG7EI8_V:
4181 case RISCV::VLOXSEG7EI16_V:
4182 case RISCV::VLOXSEG7EI32_V:
4183 case RISCV::VLOXSEG7EI64_V:
4184 case RISCV::VLUXSEG7EI8_V:
4185 case RISCV::VLUXSEG7EI16_V:
4186 case RISCV::VLUXSEG7EI32_V:
4187 case RISCV::VLUXSEG7EI64_V:
4188 return 7;
4189 case RISCV::VLOXSEG8EI8_V:
4190 case RISCV::VLOXSEG8EI16_V:
4191 case RISCV::VLOXSEG8EI32_V:
4192 case RISCV::VLOXSEG8EI64_V:
4193 case RISCV::VLUXSEG8EI8_V:
4194 case RISCV::VLUXSEG8EI16_V:
4195 case RISCV::VLUXSEG8EI32_V:
4196 case RISCV::VLUXSEG8EI64_V:
4197 return 8;
4198 }
4199}
4200
4202 if (getRISCVMCRegisterClass(RISCV::VRM2RegClassID).contains(Reg))
4203 return 2;
4204 if (getRISCVMCRegisterClass(RISCV::VRM4RegClassID).contains(Reg))
4205 return 4;
4206 if (getRISCVMCRegisterClass(RISCV::VRM8RegClassID).contains(Reg))
4207 return 8;
4208 return 1;
4209}
4210
4211static bool isZvvfmmScaleOpcode(unsigned Opcode) {
4212 switch (Opcode) {
4213 case RISCV::VFWMMACC_VV_SCALE:
4214 case RISCV::VFQMMACC_VV_SCALE:
4215 case RISCV::VF8WMMACC_VV_SCALE:
4216 case RISCV::VFWIMMACC_VV:
4217 case RISCV::VFQIMMACC_VV:
4218 case RISCV::VF8WIMMACC_VV:
4219 return true;
4220 default:
4221 return false;
4222 }
4223}
4224
4225bool RISCVAsmParser::validateInstruction(MCInst &Inst,
4227 unsigned Opcode = Inst.getOpcode();
4228
4229 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
4230 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
4231 MCRegister DestReg = Inst.getOperand(0).getReg();
4232 MCRegister TempReg = Inst.getOperand(1).getReg();
4233 if (DestReg == TempReg) {
4234 SMLoc Loc = Operands.back()->getStartLoc();
4235 return Error(Loc, "the temporary vector register cannot be the same as "
4236 "the destination register");
4237 }
4238 }
4239
4240 if (Opcode == RISCV::PseudoVMSGEU_VX_M || Opcode == RISCV::PseudoVMSGE_VX_M) {
4241 MCRegister DestReg = Inst.getOperand(0).getReg();
4242 MCRegister MaskReg = Inst.getOperand(3).getReg();
4243 if (MaskReg == RISCV::V0 && DestReg == RISCV::V0) {
4244 SMLoc Loc = Operands.back()->getStartLoc();
4245 return Error(Loc, "the destination vector register cannot overlap the "
4246 "mask register unless a temporary register is "
4247 "provided");
4248 }
4249 }
4250
4251 if (Opcode == RISCV::CV_INSERT &&
4252 Inst.getOperand(3).getImm() + Inst.getOperand(4).getImm() >= 32)
4253 return Error(Operands[3]->getStartLoc(),
4254 "the sum of the immediate operands must be less than 32");
4255
4256 switch (Opcode) {
4257 default:
4258 break;
4259 case RISCV::TH_LBIA:
4260 case RISCV::TH_LBIB:
4261 case RISCV::TH_LBUIA:
4262 case RISCV::TH_LBUIB:
4263 case RISCV::TH_LHIA:
4264 case RISCV::TH_LHIB:
4265 case RISCV::TH_LHUIA:
4266 case RISCV::TH_LHUIB:
4267 case RISCV::TH_LWIA:
4268 case RISCV::TH_LWIB:
4269 case RISCV::TH_LWUIA:
4270 case RISCV::TH_LWUIB:
4271 case RISCV::TH_LDIA:
4272 case RISCV::TH_LDIB:
4273 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4274 return Error(Operands[1]->getStartLoc(), "rd and rs1 must be different");
4275 break;
4276 case RISCV::TH_LDD:
4277 case RISCV::TH_LWUD:
4278 case RISCV::TH_LWD: {
4279 MCRegister Rd1 = Inst.getOperand(0).getReg();
4280 MCRegister Rd2 = Inst.getOperand(1).getReg();
4281 MCRegister Rs1 = Inst.getOperand(2).getReg();
4282 // The encoding with overlapping rs1, rd1, and rd2 is reserved for XTHead
4283 // load pair.
4284 if (Rs1 == Rd1 || Rs1 == Rd2 || Rd1 == Rd2) {
4285 SMLoc Loc = Operands[1]->getStartLoc();
4286 return Error(Loc, "rs1, rd1, and rd2 cannot overlap");
4287 }
4288 break;
4289 }
4290 }
4291
4292 if (Opcode == RISCV::CM_MVSA01 || Opcode == RISCV::QC_CM_MVSA01) {
4293 MCRegister Rs1 = Inst.getOperand(0).getReg();
4294 MCRegister Rs2 = Inst.getOperand(1).getReg();
4295 if (Rs1 == Rs2) {
4296 SMLoc Loc = Operands[1]->getStartLoc();
4297 return Error(Loc, "rs1 and rs2 must be different");
4298 }
4299 }
4300
4301 if (isZvvfmmScaleOpcode(Opcode)) {
4302 auto CheckOperandDoesNotOverlapV0 = [&](int OperandIdx,
4303 unsigned ParsedIdx) {
4304 if (Inst.getOperand(OperandIdx).getReg() == RISCV::V0)
4305 return Error(Operands[ParsedIdx]->getStartLoc(),
4306 "vd, vs1, and vs2 cannot overlap v0.scale");
4307 return false;
4308 };
4309
4310 int DestIdx =
4311 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
4312 int VS1Idx =
4313 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
4314 int VS2Idx =
4315 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
4316 assert(DestIdx >= 0 && VS1Idx >= 0 && VS2Idx >= 0 &&
4317 "Unexpected Zvvfmm scaled operand list");
4318
4319 if (CheckOperandDoesNotOverlapV0(DestIdx, 1) ||
4320 CheckOperandDoesNotOverlapV0(VS1Idx, 2) ||
4321 CheckOperandDoesNotOverlapV0(VS2Idx, 3))
4322 return true;
4323 }
4324
4325 const MCInstrDesc &MCID = MII.get(Opcode);
4326 if (!(MCID.TSFlags & RISCVII::RVVConstraintMask))
4327 return false;
4328
4329 int DestIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
4330 MCRegister DestReg = Inst.getOperand(DestIdx).getReg();
4331
4332 // Operands[1] or Operands[2] will be the first operand, DestReg.
4333 const MCParsedAsmOperand *ParsedOp = Operands[1].get();
4334 if (!ParsedOp->isReg()) {
4335 // XSfvcp instructions may have an immediate before vd.
4336 // FIXME: Is there a better way to do this?
4337 ParsedOp = Operands[2].get();
4338 }
4339 assert(ParsedOp->getReg() == DestReg && "Can't find parsed dest operand");
4340 SMLoc Loc = ParsedOp->getStartLoc();
4341
4342 unsigned Lmul = getLMULFromVectorRegister(DestReg);
4343 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4344 unsigned DestEncoding = RI->getEncodingValue(DestReg);
4345 if (MCID.TSFlags & RISCVII::VS2Constraint) {
4346 int VS2Idx =
4347 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
4348 assert(VS2Idx >= 0 && "No vs2 operand?");
4349 unsigned CheckEncoding =
4350 RI->getEncodingValue(Inst.getOperand(VS2Idx).getReg());
4351 unsigned NF = getNFforLXSEG(Opcode);
4352 for (unsigned i = 0; i < std::max(NF, Lmul); i++) {
4353 if ((DestEncoding + i) == CheckEncoding)
4354 return Error(Loc, "the destination vector register group cannot overlap"
4355 " the source vector register group");
4356 }
4357 }
4358 if (MCID.TSFlags & RISCVII::VS1Constraint) {
4359 int VS1Idx =
4360 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
4361 // FIXME: The vs1 constraint is used on scalar and imm instructions so we
4362 // need to check that the operand exists.
4363 if (VS1Idx >= 0) {
4364 unsigned CheckEncoding =
4365 RI->getEncodingValue(Inst.getOperand(VS1Idx).getReg());
4366 for (unsigned i = 0; i < Lmul; i++) {
4367 if ((DestEncoding + i) == CheckEncoding)
4368 return Error(Loc,
4369 "the destination vector register group cannot overlap"
4370 " the source vector register group");
4371 }
4372 }
4373 }
4374
4375 if (MCID.TSFlags & RISCVII::VMConstraint) {
4376 int VMIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vm);
4377 assert(VMIdx >= 0 && "No vm operand?");
4378
4379 if (DestReg == RISCV::V0) {
4380 if (MCID.operands()[Inst.getNumOperands() - 1].OperandType !=
4382 return Error(Loc, "the destination vector register group cannot be V0");
4383
4384 // Regardless masked or unmasked version, the number of operands is the
4385 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
4386 // actually. We need to check the operand to see whether it is masked or
4387 // not.
4388 MCRegister CheckReg = Inst.getOperand(VMIdx).getReg();
4389 assert((!CheckReg.isValid() || CheckReg == RISCV::V0) &&
4390 "Unexpected mask operand register");
4391 if (CheckReg.isValid())
4392 return Error(Loc, "the destination vector register group cannot overlap"
4393 " the mask register");
4394 }
4395 }
4396
4398 // smt.vmadot with sp and hp: the vmask operand (only use V0 or V1) must not
4399 // overlap with any of vd, vs1, or vs2.
4400 int VMaskIdx =
4401 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vmask);
4402 MCRegister MaskReg = Inst.getOperand(VMaskIdx).getReg();
4403 if (MaskReg != RISCV::V0 && MaskReg != RISCV::V1)
4404 return Error(Operands[VMaskIdx]->getStartLoc(),
4405 "vmask operand only supports v0 or v1");
4406
4407 unsigned MaskEnc = RI->getEncodingValue(MaskReg);
4408 RISCV::OpName RegOps[] = {RISCV::OpName::vd, RISCV::OpName::vs1,
4409 RISCV::OpName::vs2};
4410 for (RISCV::OpName OpN : RegOps) {
4411 int Idx = RISCV::getNamedOperandIdx(Inst.getOpcode(), OpN);
4412 if (Idx < 0 || !Inst.getOperand(Idx).isReg())
4413 continue;
4414 MCRegister Reg = Inst.getOperand(Idx).getReg();
4415 unsigned RegEnc = RI->getEncodingValue(Reg);
4416 unsigned RegLmul = getLMULFromVectorRegister(Reg);
4417 for (unsigned i = 0; i < RegLmul; i++) {
4418 if ((RegEnc + i) == MaskEnc) {
4419 SMLoc Loc = Operands[Idx]->getStartLoc();
4420 return Error(Loc,
4421 Twine("register conflicts with vmask register ") +
4422 RISCVInstPrinter::getRegisterName(CLOpts, MaskReg));
4423 }
4424 }
4425 }
4426 }
4427
4428 return false;
4429}
4430
4431bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
4433 MCStreamer &Out) {
4434 Inst.setLoc(IDLoc);
4435
4436 switch (Inst.getOpcode()) {
4437 default:
4438 break;
4439 case RISCV::MOP_RR_7: {
4440 // Remap mop.rr.7 x0, x0, x1/x5 to sspush x1/x5.
4441 if (Inst.getOperand(0).getReg() == RISCV::X0 &&
4442 Inst.getOperand(1).getReg() == RISCV::X0 &&
4443 (Inst.getOperand(2).getReg() == RISCV::X1 ||
4444 Inst.getOperand(2).getReg() == RISCV::X5)) {
4445 emitToStreamer(
4446 Out, MCInstBuilder(RISCV::SSPUSH).addOperand(Inst.getOperand(2)));
4447 return false;
4448 }
4449 break;
4450 }
4451 case RISCV::MOP_R_28: {
4452 // Remap mop.r.28 x0, x1/x5 to sspopchk x1/x5.
4453 if (Inst.getOperand(0).getReg() == RISCV::X0 &&
4454 (Inst.getOperand(1).getReg() == RISCV::X1 ||
4455 Inst.getOperand(1).getReg() == RISCV::X5)) {
4456 emitToStreamer(
4457 Out, MCInstBuilder(RISCV::SSPOPCHK).addOperand(Inst.getOperand(1)));
4458 return false;
4459 }
4460 // Remap mop.r.28 rN, x0 to ssrdp rN.
4461 if (Inst.getOperand(0).getReg() != RISCV::X0 &&
4462 Inst.getOperand(1).getReg() == RISCV::X0) {
4463 emitToStreamer(
4464 Out, MCInstBuilder(RISCV::SSRDP).addOperand(Inst.getOperand(0)));
4465 return false;
4466 }
4467 break;
4468 }
4469 case RISCV::PseudoC_ADDI_NOP: {
4470 if (Inst.getOperand(2).getImm() == 0)
4471 emitToStreamer(Out, MCInstBuilder(RISCV::C_NOP));
4472 else
4473 emitToStreamer(
4474 Out, MCInstBuilder(RISCV::C_NOP_HINT).addOperand(Inst.getOperand(2)));
4475 return false;
4476 }
4477 case RISCV::PACK: {
4478 // Convert PACK wth RS2==X0 to ZEXT_H_RV32 to match disassembler output.
4479 if (Inst.getOperand(2).getReg() != RISCV::X0)
4480 break;
4481 if (getSTI().hasFeature(RISCV::Feature64Bit))
4482 break;
4483 emitToStreamer(Out, MCInstBuilder(RISCV::ZEXT_H_RV32)
4484 .addOperand(Inst.getOperand(0))
4485 .addOperand(Inst.getOperand(1)));
4486 return false;
4487 }
4488 case RISCV::PACKW: {
4489 // Convert PACKW with RS2==X0 to ZEXT_H_RV64 to match disassembler output.
4490 if (Inst.getOperand(2).getReg() != RISCV::X0)
4491 break;
4492 emitToStreamer(Out, MCInstBuilder(RISCV::ZEXT_H_RV64)
4493 .addOperand(Inst.getOperand(0))
4494 .addOperand(Inst.getOperand(1)));
4495 return false;
4496 }
4497 case RISCV::PseudoLLAImm:
4498 case RISCV::PseudoLAImm:
4499 case RISCV::PseudoLI: {
4500 MCRegister Reg = Inst.getOperand(0).getReg();
4501 const MCOperand &Op1 = Inst.getOperand(1);
4502 if (Op1.isExpr()) {
4503 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
4504 // Just convert to an addi. This allows compatibility with gas.
4505 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
4506 .addReg(Reg)
4507 .addReg(RISCV::X0)
4508 .addExpr(Op1.getExpr()));
4509 return false;
4510 }
4511 int64_t Imm = Inst.getOperand(1).getImm();
4512 // On RV32 the immediate here can either be a signed or an unsigned
4513 // 32-bit number. Sign extension has to be performed to ensure that Imm
4514 // represents the expected signed 64-bit number.
4515 if (!isRV64())
4517 emitLoadImm(Reg, Imm, Out);
4518 return false;
4519 }
4520 case RISCV::PseudoLLA:
4521 emitLoadLocalAddress(Inst, IDLoc, Out);
4522 return false;
4523 case RISCV::PseudoLGA:
4524 emitLoadGlobalAddress(Inst, IDLoc, Out);
4525 return false;
4526 case RISCV::PseudoLA:
4527 emitLoadAddress(Inst, IDLoc, Out);
4528 return false;
4529 case RISCV::PseudoLA_TLS_IE:
4530 emitLoadTLSIEAddress(Inst, IDLoc, Out);
4531 return false;
4532 case RISCV::PseudoLA_TLS_GD:
4533 emitLoadTLSGDAddress(Inst, IDLoc, Out);
4534 return false;
4535 case RISCV::PseudoLB:
4536 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
4537 return false;
4538 case RISCV::PseudoLBU:
4539 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
4540 return false;
4541 case RISCV::PseudoLH:
4542 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
4543 return false;
4544 case RISCV::PseudoLHU:
4545 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
4546 return false;
4547 case RISCV::PseudoLW:
4548 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
4549 return false;
4550 case RISCV::PseudoLWU:
4551 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
4552 return false;
4553 case RISCV::PseudoLD:
4554 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
4555 return false;
4556 case RISCV::PseudoLD_RV32:
4557 emitLoadStoreSymbol(Inst, RISCV::LD_RV32, IDLoc, Out, /*HasTmpReg=*/false);
4558 return false;
4559 case RISCV::PseudoFLH:
4560 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
4561 return false;
4562 case RISCV::PseudoFLW:
4563 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
4564 return false;
4565 case RISCV::PseudoFLD:
4566 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
4567 return false;
4568 case RISCV::PseudoFLQ:
4569 emitLoadStoreSymbol(Inst, RISCV::FLQ, IDLoc, Out, /*HasTmpReg=*/true);
4570 return false;
4571 case RISCV::PseudoSB:
4572 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
4573 return false;
4574 case RISCV::PseudoSH:
4575 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
4576 return false;
4577 case RISCV::PseudoSW:
4578 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
4579 return false;
4580 case RISCV::PseudoSD:
4581 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
4582 return false;
4583 case RISCV::PseudoSD_RV32:
4584 emitLoadStoreSymbol(Inst, RISCV::SD_RV32, IDLoc, Out, /*HasTmpReg=*/true);
4585 return false;
4586 case RISCV::PseudoQC_E_LB:
4587 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLB, IDLoc, Out,
4588 /*HasTmpReg=*/false);
4589 return false;
4590 case RISCV::PseudoQC_E_LBU:
4591 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLBU, IDLoc, Out,
4592 /*HasTmpReg=*/false);
4593 return false;
4594 case RISCV::PseudoQC_E_LH:
4595 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLH, IDLoc, Out,
4596 /*HasTmpReg=*/false);
4597 return false;
4598 case RISCV::PseudoQC_E_LHU:
4599 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLHU, IDLoc, Out,
4600 /*HasTmpReg=*/false);
4601 return false;
4602 case RISCV::PseudoQC_E_LW:
4603 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessLW, IDLoc, Out,
4604 /*HasTmpReg=*/false);
4605 return false;
4606 case RISCV::PseudoQC_E_SB:
4607 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessSB, IDLoc, Out,
4608 /*HasTmpReg=*/true);
4609 return false;
4610 case RISCV::PseudoQC_E_SH:
4611 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessSH, IDLoc, Out,
4612 /*HasTmpReg=*/true);
4613 return false;
4614 case RISCV::PseudoQC_E_SW:
4615 emitQCELILoadStoreSymbol(Inst, RISCV::PseudoQCAccessSW, IDLoc, Out,
4616 /*HasTmpReg=*/true);
4617 return false;
4618 case RISCV::PseudoFSH:
4619 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
4620 return false;
4621 case RISCV::PseudoFSW:
4622 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
4623 return false;
4624 case RISCV::PseudoFSD:
4625 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
4626 return false;
4627 case RISCV::PseudoFSQ:
4628 emitLoadStoreSymbol(Inst, RISCV::FSQ, IDLoc, Out, /*HasTmpReg=*/true);
4629 return false;
4630 case RISCV::PseudoAddTPRel:
4631 if (checkPseudoAddTPRel(Inst, Operands))
4632 return true;
4633 break;
4634 case RISCV::PseudoTLSDESCCall:
4635 if (checkPseudoTLSDESCCall(Inst, Operands))
4636 return true;
4637 break;
4638 case RISCV::PseudoSEXT_B:
4639 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
4640 return false;
4641 case RISCV::PseudoSEXT_H:
4642 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
4643 return false;
4644 case RISCV::PseudoZEXT_H:
4645 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
4646 return false;
4647 case RISCV::PseudoZEXT_W:
4648 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
4649 return false;
4650 case RISCV::PseudoVMSGEU_VX_M:
4651 case RISCV::PseudoVMSGEU_VX_M_T:
4652 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
4653 return false;
4654 case RISCV::PseudoVMSGE_VX_M:
4655 case RISCV::PseudoVMSGE_VX_M_T:
4656 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
4657 return false;
4658 case RISCV::PseudoVMSGE_VI:
4659 case RISCV::PseudoVMSLT_VI: {
4660 // These instructions are signed and so is immediate so we can subtract one
4661 // and change the opcode.
4662 int64_t Imm = Inst.getOperand(2).getImm();
4663 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
4664 : RISCV::VMSLE_VI;
4665 emitToStreamer(Out, MCInstBuilder(Opc)
4666 .addOperand(Inst.getOperand(0))
4667 .addOperand(Inst.getOperand(1))
4668 .addImm(Imm - 1)
4669 .addOperand(Inst.getOperand(3))
4670 .setLoc(IDLoc));
4671 return false;
4672 }
4673 case RISCV::PseudoVMSGEU_VI:
4674 case RISCV::PseudoVMSLTU_VI: {
4675 int64_t Imm = Inst.getOperand(2).getImm();
4676 // Unsigned comparisons are tricky because the immediate is signed. If the
4677 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
4678 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
4679 // vmsne v0, v1, v1 which is always false.
4680 if (Imm == 0) {
4681 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4682 ? RISCV::VMSEQ_VV
4683 : RISCV::VMSNE_VV;
4684 emitToStreamer(Out, MCInstBuilder(Opc)
4685 .addOperand(Inst.getOperand(0))
4686 .addOperand(Inst.getOperand(1))
4687 .addOperand(Inst.getOperand(1))
4688 .addOperand(Inst.getOperand(3))
4689 .setLoc(IDLoc));
4690 } else {
4691 // Other immediate values can subtract one like signed.
4692 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4693 ? RISCV::VMSGTU_VI
4694 : RISCV::VMSLEU_VI;
4695 emitToStreamer(Out, MCInstBuilder(Opc)
4696 .addOperand(Inst.getOperand(0))
4697 .addOperand(Inst.getOperand(1))
4698 .addImm(Imm - 1)
4699 .addOperand(Inst.getOperand(3))
4700 .setLoc(IDLoc));
4701 }
4702
4703 return false;
4704 }
4705 case RISCV::PseudoCV_ELW:
4706 emitLoadStoreSymbol(Inst, RISCV::CV_ELW, IDLoc, Out, /*HasTmpReg=*/false);
4707 return false;
4708 }
4709
4710 emitToStreamer(Out, Inst);
4711 return false;
4712}
4713
4714extern "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)
SDValue Pred
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID)
uint64_t uint64_t
uint64_t Imm
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:665
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:211
#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 bool regClassIsYGPR(const MCRegisterClass &RC)
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:480
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:452
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:415
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
MCRegisterClass - Base class of TargetRegisterClass.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
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.
ArrayRef< SubtargetFeatureKV > getAllProcessorFeatures() const
Return processor features.
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.
const AArch64MCOptions & getCLOpts(const MCTargetOptions &Options)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
uint16_t StackAdjustment(const RuntimeFunction &RF)
StackAdjustment - calculated stack adjustment in words.
Definition ARMWinEH.h:200
LLVM_ABI std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
MCExpr const & getExpr(MCExpr const &Expr)
Expected< ABI > computeTargetABI(const MCSubtargetInfo &STI, StringRef ABIName)
LLVM_ABI const TagNameMap & getRISCVAttributeTags()
static RoundingMode stringToRoundingMode(StringRef Str)
llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseFeatureBits(const MCSubtargetInfo &STI)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, MCRegister DestReg, SmallVectorImpl< MCInst > &Insts)
bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
LLVM_ABI unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt)
static bool isValidLMUL(unsigned LMUL, bool Fractional)
static bool isValidSEW(unsigned SEW)
LLVM_ABI void printVType(unsigned VType, raw_ostream &OS)
static bool isValidXSfmmVType(unsigned VTypeI)
LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic, bool AltFmt=false)
unsigned encodeRegList(MCRegister EndReg, bool IsRVE=false)
static unsigned getStackAdjBase(unsigned RlistVal, bool IsRV64)
void printRegList(unsigned RlistEncode, raw_ostream &OS)
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:572
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,...