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