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