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