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