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