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