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 return Error(ErrorLoc,
2465 "operand must be "
2466 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2467}
2468
2469ParseStatus RISCVAsmParser::parseXSfmmVType(OperandVector &Operands) {
2470 SMLoc S = getLoc();
2471
2472 unsigned Widen = 0;
2473 unsigned SEW = 0;
2474 bool AltFmt = false;
2475 StringRef Identifier;
2476
2477 if (getTok().isNot(AsmToken::Identifier))
2478 goto Fail;
2479
2480 Identifier = getTok().getIdentifier();
2481
2482 if (!Identifier.consume_front("e"))
2483 goto Fail;
2484
2485 if (Identifier.getAsInteger(10, SEW)) {
2486 if (Identifier != "16alt")
2487 goto Fail;
2488
2489 AltFmt = true;
2490 SEW = 16;
2491 }
2492 if (!RISCVVType::isValidSEW(SEW))
2493 goto Fail;
2494
2495 Lex();
2496
2497 if (!parseOptionalToken(AsmToken::Comma))
2498 goto Fail;
2499
2500 if (getTok().isNot(AsmToken::Identifier))
2501 goto Fail;
2502
2503 Identifier = getTok().getIdentifier();
2504
2505 if (!Identifier.consume_front("w"))
2506 goto Fail;
2507 if (Identifier.getAsInteger(10, Widen))
2508 goto Fail;
2509 if (Widen != 1 && Widen != 2 && Widen != 4)
2510 goto Fail;
2511
2512 Lex();
2513
2514 if (getLexer().is(AsmToken::EndOfStatement)) {
2515 Operands.push_back(RISCVOperand::createVType(
2516 RISCVVType::encodeXSfmmVType(SEW, Widen, AltFmt), S));
2517 return ParseStatus::Success;
2518 }
2519
2520Fail:
2521 return generateXSfmmVTypeError(S);
2522}
2523
2524bool RISCVAsmParser::generateXSfmmVTypeError(SMLoc ErrorLoc) {
2525 return Error(ErrorLoc, "operand must be e[8|16|16alt|32|64],w[1|2|4]");
2526}
2527
2528ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2529 if (getLexer().isNot(AsmToken::Identifier))
2530 return ParseStatus::NoMatch;
2531
2532 StringRef Name = getLexer().getTok().getIdentifier();
2533 if (!Name.consume_back(".t")) {
2534 // Non-register identifiers may belong to another optional operand in an
2535 // overloaded mnemonic. Let the matcher try those alternatives.
2536 if (matchRegisterNameHelper(Name))
2537 return Error(getLoc(), "expected '.t' suffix");
2538 return ParseStatus::NoMatch;
2539 }
2540 MCRegister Reg = matchRegisterNameHelper(Name);
2541
2542 if (!Reg)
2543 return ParseStatus::NoMatch;
2544 if (Reg != RISCV::V0)
2545 return ParseStatus::NoMatch;
2546 SMLoc S = getLoc();
2547 SMLoc E = getTok().getEndLoc();
2548 getLexer().Lex();
2549 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2550 return ParseStatus::Success;
2551}
2552
2553ParseStatus RISCVAsmParser::parseVScaleReg(OperandVector &Operands) {
2554 if (getLexer().isNot(AsmToken::Identifier))
2555 return ParseStatus::NoMatch;
2556
2557 StringRef Name = getLexer().getTok().getIdentifier();
2558 if (!Name.consume_back(".scale"))
2559 return Error(getLoc(), "expected '.scale' suffix");
2560 MCRegister Reg = matchRegisterNameHelper(Name);
2561
2562 if (!Reg)
2563 return ParseStatus::NoMatch;
2564 if (Reg != RISCV::V0)
2565 return ParseStatus::NoMatch;
2566 SMLoc S = getLoc();
2567 SMLoc E = getTok().getEndLoc();
2568 getLexer().Lex();
2569 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2570 return ParseStatus::Success;
2571}
2572
2573ParseStatus RISCVAsmParser::parseTileLambda(OperandVector &Operands) {
2574 if (getLexer().isNot(AsmToken::Identifier))
2575 return ParseStatus::NoMatch;
2576
2577 SMLoc S = getLoc();
2578 StringRef Name = getLexer().getTok().getIdentifier();
2579 if (!Name.consume_front("L") && !Name.consume_front("l"))
2580 return ParseStatus::NoMatch;
2581
2582 unsigned Lambda;
2583 if (Name.getAsInteger(10, Lambda) || !isPowerOf2_32(Lambda) || Lambda >= 128)
2584 return Error(S, "operand must be L1, L2, L4, L8, L16, L32, or L64");
2585
2586 unsigned EncodedLambda = Log2_32(Lambda) + 1;
2587
2588 SMLoc E = getTok().getEndLoc();
2589 getLexer().Lex();
2590 Operands.push_back(RISCVOperand::createExpr(
2591 MCConstantExpr::create(EncodedLambda, getContext()), S, E, isRV64()));
2592 return ParseStatus::Success;
2593}
2594
2595ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
2596 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2597 return ParseStatus::NoMatch;
2598
2599 return parseGPRAsFPR(Operands);
2600}
2601
2602ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2603 if (getLexer().isNot(AsmToken::Identifier))
2604 return ParseStatus::NoMatch;
2605
2606 StringRef Name = getLexer().getTok().getIdentifier();
2607 MCRegister Reg = matchRegisterNameHelper(Name);
2608
2609 if (!Reg)
2610 return ParseStatus::NoMatch;
2611 SMLoc S = getLoc();
2612 SMLoc E = getTok().getEndLoc();
2613 getLexer().Lex();
2614 Operands.push_back(RISCVOperand::createReg(
2615 Reg, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2616 return ParseStatus::Success;
2617}
2618
2619ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
2620 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2621 return ParseStatus::NoMatch;
2622
2623 if (getLexer().isNot(AsmToken::Identifier))
2624 return ParseStatus::NoMatch;
2625
2626 StringRef Name = getLexer().getTok().getIdentifier();
2627 MCRegister Reg = matchRegisterNameHelper(Name);
2628
2629 if (!Reg)
2630 return ParseStatus::NoMatch;
2631
2632 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2633 return ParseStatus::NoMatch;
2634
2635 if ((Reg - RISCV::X0) & 1) {
2636 // Only report the even register error if we have at least Zfinx so we know
2637 // some FP is enabled. We already checked F earlier.
2638 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2639 return TokError("double precision floating point operands must use even "
2640 "numbered X register");
2641 return ParseStatus::NoMatch;
2642 }
2643
2644 SMLoc S = getLoc();
2645 SMLoc E = getTok().getEndLoc();
2646 getLexer().Lex();
2647
2648 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2649 MCRegister Pair = RI->getMatchingSuperReg(
2650 Reg, RISCV::sub_gpr_even,
2651 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2652 Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));
2653 return ParseStatus::Success;
2654}
2655
2656template <bool IsRV64>
2657ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2658 return parseGPRPair(Operands, IsRV64);
2659}
2660
2661ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2662 bool IsRV64Inst) {
2663 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2664 // RV64 as it will prevent matching the RV64 version of the same instruction
2665 // that doesn't use a GPRPair.
2666 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2667 // still parse as a pair.
2668 if (!IsRV64Inst && isRV64())
2669 return ParseStatus::NoMatch;
2670
2671 if (getLexer().isNot(AsmToken::Identifier))
2672 return ParseStatus::NoMatch;
2673
2674 StringRef Name = getLexer().getTok().getIdentifier();
2675 MCRegister Reg = matchRegisterNameHelper(Name);
2676
2677 if (!Reg)
2678 return ParseStatus::NoMatch;
2679
2680 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2681 return ParseStatus::NoMatch;
2682
2683 if ((Reg - RISCV::X0) & 1)
2684 return TokError("register must be even");
2685
2686 SMLoc S = getLoc();
2687 SMLoc E = getTok().getEndLoc();
2688 getLexer().Lex();
2689
2690 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2691 MCRegister Pair = RI->getMatchingSuperReg(
2692 Reg, RISCV::sub_gpr_even,
2693 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2694 Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2695 return ParseStatus::Success;
2696}
2697
2698ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2699 if (getLexer().isNot(AsmToken::Identifier))
2700 return TokError(
2701 "operand must be a valid floating point rounding mode mnemonic");
2702
2703 StringRef Str = getLexer().getTok().getIdentifier();
2705
2706 if (FRM == RISCVFPRndMode::Invalid)
2707 return TokError(
2708 "operand must be a valid floating point rounding mode mnemonic");
2709
2710 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2711 Lex(); // Eat identifier token.
2712 return ParseStatus::Success;
2713}
2714
2715ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2716 const AsmToken &Tok = getLexer().getTok();
2717
2718 if (Tok.is(AsmToken::Integer)) {
2719 if (Tok.getIntVal() != 0)
2720 goto ParseFail;
2721
2722 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2723 Lex();
2724 return ParseStatus::Success;
2725 }
2726
2727 if (Tok.is(AsmToken::Identifier)) {
2728 StringRef Str = Tok.getIdentifier();
2729
2730 // Letters must be unique, taken from 'iorw', and in ascending order. This
2731 // holds as long as each individual character is one of 'iorw' and is
2732 // greater than the previous character.
2733 unsigned Imm = 0;
2734 bool Valid = true;
2735 char Prev = '\0';
2736 for (char c : Str) {
2737 switch (c) {
2738 default:
2739 Valid = false;
2740 break;
2741 case 'i':
2743 break;
2744 case 'o':
2746 break;
2747 case 'r':
2749 break;
2750 case 'w':
2752 break;
2753 }
2754
2755 if (c <= Prev) {
2756 Valid = false;
2757 break;
2758 }
2759 Prev = c;
2760 }
2761
2762 if (!Valid)
2763 goto ParseFail;
2764
2765 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2766 Lex();
2767 return ParseStatus::Success;
2768 }
2769
2770ParseFail:
2771 return TokError("operand must be formed of letters selected in-order from "
2772 "'iorw' or be 0");
2773}
2774
2775ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2776 if (parseToken(AsmToken::LParen, "expected '('"))
2777 return ParseStatus::Failure;
2778 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2779
2780 if (!parseRegister(Operands).isSuccess())
2781 return Error(getLoc(), "expected register");
2782
2783 if (parseToken(AsmToken::RParen, "expected ')'"))
2784 return ParseStatus::Failure;
2785 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2786
2787 return ParseStatus::Success;
2788}
2789
2790ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2791 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2792 // as one of their register operands, such as `(a0)`. This just denotes that
2793 // the register (in this case `a0`) contains a memory address.
2794 //
2795 // Normally, we would be able to parse these by putting the parens into the
2796 // instruction string. However, GNU as also accepts a zero-offset memory
2797 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2798 // with parseExpression followed by parseMemOpBaseReg, but these instructions
2799 // do not accept an immediate operand, and we do not want to add a "dummy"
2800 // operand that is silently dropped.
2801 //
2802 // Instead, we use this custom parser. This will: allow (and discard) an
2803 // offset if it is zero; require (and discard) parentheses; and add only the
2804 // parsed register operand to `Operands`.
2805 //
2806 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2807 // which will only print the register surrounded by parentheses (which GNU as
2808 // also uses as its canonical representation for these operands).
2809 std::unique_ptr<RISCVOperand> OptionalImmOp;
2810
2811 if (getLexer().isNot(AsmToken::LParen)) {
2812 // Parse an Integer token. We do not accept arbitrary constant expressions
2813 // in the offset field (because they may include parens, which complicates
2814 // parsing a lot).
2815 int64_t ImmVal;
2816 SMLoc ImmStart = getLoc();
2817 if (getParser().parseIntToken(ImmVal,
2818 "expected '(' or optional integer offset"))
2819 return ParseStatus::Failure;
2820
2821 // Create a RISCVOperand for checking later (so the error messages are
2822 // nicer), but we don't add it to Operands.
2823 SMLoc ImmEnd = getLoc();
2824 OptionalImmOp =
2825 RISCVOperand::createExpr(MCConstantExpr::create(ImmVal, getContext()),
2826 ImmStart, ImmEnd, isRV64());
2827 }
2828
2829 if (parseToken(AsmToken::LParen,
2830 OptionalImmOp ? "expected '(' after optional integer offset"
2831 : "expected '(' or optional integer offset"))
2832 return ParseStatus::Failure;
2833
2834 if (!parseRegister(Operands).isSuccess())
2835 return Error(getLoc(), "expected register");
2836
2837 if (parseToken(AsmToken::RParen, "expected ')'"))
2838 return ParseStatus::Failure;
2839
2840 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2841 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2842 return Error(
2843 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2844 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2845
2846 return ParseStatus::Success;
2847}
2848
2849ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2850 // RR : a2(a1)
2851 if (getLexer().getKind() != AsmToken::Identifier)
2852 return ParseStatus::NoMatch;
2853
2854 SMLoc S = getLoc();
2855 StringRef OffsetRegName = getLexer().getTok().getIdentifier();
2856 MCRegister OffsetReg = matchRegisterNameHelper(OffsetRegName);
2857 if (!OffsetReg ||
2858 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(OffsetReg))
2859 return Error(getLoc(), "expected GPR register");
2860 getLexer().Lex();
2861
2862 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
2863 return ParseStatus::Failure;
2864
2865 if (getLexer().getKind() != AsmToken::Identifier)
2866 return Error(getLoc(), "expected GPR register");
2867
2868 StringRef BaseRegName = getLexer().getTok().getIdentifier();
2869 MCRegister BaseReg = matchRegisterNameHelper(BaseRegName);
2870 if (!BaseReg ||
2871 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(BaseReg))
2872 return Error(getLoc(), "expected GPR register");
2873 getLexer().Lex();
2874
2875 if (parseToken(AsmToken::RParen, "expected ')'"))
2876 return ParseStatus::Failure;
2877
2878 Operands.push_back(RISCVOperand::createRegReg(BaseReg, OffsetReg, S));
2879
2880 return ParseStatus::Success;
2881}
2882
2883// RegList: {ra [, s0[-sN]]}
2884// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
2885
2886// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
2887// must include `fp`/`s0` in the list:
2888// RegList: {ra, s0[-sN]}
2889// XRegList: {x1, x8[-x9][, x18[-xN]]}
2890ParseStatus RISCVAsmParser::parseRegList(OperandVector &Operands,
2891 bool MustIncludeS0) {
2892 if (getTok().isNot(AsmToken::LCurly))
2893 return ParseStatus::NoMatch;
2894
2895 SMLoc S = getLoc();
2896
2897 Lex();
2898
2899 bool UsesXRegs;
2900 MCRegister RegEnd;
2901 do {
2902 if (getTok().isNot(AsmToken::Identifier))
2903 return Error(getLoc(), "invalid register");
2904
2905 StringRef RegName = getTok().getIdentifier();
2906 MCRegister Reg = matchRegisterNameHelper(RegName);
2907 if (!Reg)
2908 return Error(getLoc(), "invalid register");
2909
2910 if (!RegEnd) {
2911 UsesXRegs = RegName[0] == 'x';
2912 if (Reg != RISCV::X1)
2913 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2914 } else if (RegEnd == RISCV::X1) {
2915 if (Reg != RISCV::X8 || (UsesXRegs != (RegName[0] == 'x')))
2916 return Error(getLoc(), Twine("register must be '") +
2917 (UsesXRegs ? "x8" : "s0") + "'");
2918 } else if (RegEnd == RISCV::X9 && UsesXRegs) {
2919 if (Reg != RISCV::X18 || (RegName[0] != 'x'))
2920 return Error(getLoc(), "register must be 'x18'");
2921 } else {
2922 return Error(getLoc(), "too many register ranges");
2923 }
2924
2925 RegEnd = Reg;
2926
2927 Lex();
2928
2929 SMLoc MinusLoc = getLoc();
2930 if (parseOptionalToken(AsmToken::Minus)) {
2931 if (RegEnd == RISCV::X1)
2932 return Error(MinusLoc, Twine("register '") + (UsesXRegs ? "x1" : "ra") +
2933 "' cannot start a multiple register range");
2934
2935 if (getTok().isNot(AsmToken::Identifier))
2936 return Error(getLoc(), "invalid register");
2937
2938 StringRef RegName = getTok().getIdentifier();
2939 MCRegister Reg = matchRegisterNameHelper(RegName);
2940 if (!Reg)
2941 return Error(getLoc(), "invalid register");
2942
2943 if (RegEnd == RISCV::X8) {
2944 if ((Reg != RISCV::X9 &&
2945 (UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||
2946 (UsesXRegs != (RegName[0] == 'x'))) {
2947 if (UsesXRegs)
2948 return Error(getLoc(), "register must be 'x9'");
2949 return Error(getLoc(), "register must be in the range 's1' to 's11'");
2950 }
2951 } else if (RegEnd == RISCV::X18) {
2952 if (Reg < RISCV::X19 || Reg > RISCV::X27 || (RegName[0] != 'x'))
2953 return Error(getLoc(),
2954 "register must be in the range 'x19' to 'x27'");
2955 } else
2956 llvm_unreachable("unexpected register");
2957
2958 RegEnd = Reg;
2959
2960 Lex();
2961 }
2962 } while (parseOptionalToken(AsmToken::Comma));
2963
2964 if (parseToken(AsmToken::RCurly, "expected ',' or '}'"))
2965 return ParseStatus::Failure;
2966
2967 if (RegEnd == RISCV::X26)
2968 return Error(S, "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
2969 "x18-x26}' is not supported");
2970
2971 auto Encode = RISCVZC::encodeRegList(RegEnd, isRVE());
2972 assert(Encode != RISCVZC::INVALID_RLIST);
2973
2974 if (MustIncludeS0 && Encode == RISCVZC::RA)
2975 return Error(S, "register list must include 's0' or 'x8'");
2976
2977 Operands.push_back(RISCVOperand::createRegList(Encode, S));
2978
2979 return ParseStatus::Success;
2980}
2981
2982ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2983 bool ExpectNegative) {
2984 SMLoc S = getLoc();
2985 bool Negative = parseOptionalToken(AsmToken::Minus);
2986
2987 if (getTok().isNot(AsmToken::Integer))
2988 return ParseStatus::NoMatch;
2989
2990 int64_t StackAdjustment = getTok().getIntVal();
2991
2992 auto *RegListOp = static_cast<RISCVOperand *>(Operands.back().get());
2993 if (!RegListOp->isRegList())
2994 return ParseStatus::NoMatch;
2995
2996 unsigned RlistEncode = RegListOp->RegList.Encoding;
2997
2998 assert(RlistEncode != RISCVZC::INVALID_RLIST);
2999 unsigned StackAdjBase = RISCVZC::getStackAdjBase(RlistEncode, isRV64());
3000 if (Negative != ExpectNegative || StackAdjustment % 16 != 0 ||
3001 StackAdjustment < StackAdjBase || (StackAdjustment - StackAdjBase) > 48) {
3002 int64_t Lower = StackAdjBase;
3003 int64_t Upper = StackAdjBase + 48;
3004 if (ExpectNegative) {
3005 Lower = -Lower;
3006 Upper = -Upper;
3008 }
3009 return generateImmOutOfRangeError(S, Lower, Upper,
3010 "stack adjustment for register list must "
3011 "be a multiple of 16 bytes in the range");
3012 }
3013
3014 unsigned StackAdj = (StackAdjustment - StackAdjBase);
3015 Operands.push_back(RISCVOperand::createStackAdj(StackAdj, S));
3016 Lex();
3017 return ParseStatus::Success;
3018}
3019
3020/// Looks at a token type and creates the relevant operand from this
3021/// information, adding to Operands. If operand was parsed, returns false, else
3022/// true.
3023bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
3024 // Check if the current operand has a custom associated parser, if so, try to
3025 // custom parse the operand, or fallback to the general approach.
3026 ParseStatus Result =
3027 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
3028 if (Result.isSuccess())
3029 return false;
3030 if (Result.isFailure())
3031 return true;
3032
3033 // Attempt to parse token as a register.
3034 if (parseRegister(Operands, true).isSuccess())
3035 return false;
3036
3037 // Attempt to parse token as an expression
3038 if (parseExpression(Operands).isSuccess()) {
3039 // Parse memory base register if present
3040 if (getLexer().is(AsmToken::LParen))
3041 return !parseMemOpBaseReg(Operands).isSuccess();
3042 return false;
3043 }
3044
3045 // Finally we have exhausted all options and must declare defeat.
3046 Error(getLoc(), "unknown operand");
3047 return true;
3048}
3049
3050bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,
3051 StringRef Name, SMLoc NameLoc,
3052 OperandVector &Operands) {
3053 // Apply mnemonic aliases because the destination mnemonic may have require
3054 // custom operand parsing. The generic tblgen'erated code does this later, at
3055 // the start of MatchInstructionImpl(), but that's too late for custom
3056 // operand parsing.
3057 const FeatureBitset &AvailableFeatures = getAvailableFeatures();
3058 applyMnemonicAliases(Name, AvailableFeatures, 0);
3059
3060 // First operand is token for instruction
3061 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
3062
3063 // If there are no more operands, then finish
3064 if (getLexer().is(AsmToken::EndOfStatement)) {
3065 getParser().Lex(); // Consume the EndOfStatement.
3066 return false;
3067 }
3068
3069 // Parse first operand
3070 if (parseOperand(Operands, Name))
3071 return true;
3072
3073 // Parse until end of statement, consuming commas between operands
3074 while (parseOptionalToken(AsmToken::Comma)) {
3075 // Parse next operand
3076 if (parseOperand(Operands, Name))
3077 return true;
3078 }
3079
3080 if (getParser().parseEOL("unexpected token")) {
3081 getParser().eatToEndOfStatement();
3082 return true;
3083 }
3084 return false;
3085}
3086
3087bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
3088 RISCV::Specifier &Kind) {
3090 if (const auto *RE = dyn_cast<MCSpecifierExpr>(Expr)) {
3091 Kind = RE->getSpecifier();
3092 Expr = RE->getSubExpr();
3093 }
3094
3095 MCValue Res;
3096 if (Expr->evaluateAsRelocatable(Res, nullptr))
3097 return Res.getSpecifier() == RISCV::S_None;
3098 return false;
3099}
3100
3101bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
3102 MCValue Res;
3103 if (Expr->evaluateAsRelocatable(Res, nullptr)) {
3104 return Res.getSpecifier() == RISCV::S_None && Res.getAddSym() &&
3105 Res.getSubSym();
3106 }
3107 return false;
3108}
3109
3110ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
3111 StringRef IDVal = DirectiveID.getString();
3112
3113 if (IDVal == ".option")
3114 return parseDirectiveOption();
3115 if (IDVal == ".attribute")
3116 return parseDirectiveAttribute();
3117 if (IDVal == ".insn")
3118 return parseDirectiveInsn(DirectiveID.getLoc());
3119 if (IDVal == ".variant_cc")
3120 return parseDirectiveVariantCC();
3121
3122 return ParseStatus::NoMatch;
3123}
3124
3125bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
3126 bool FromOptionDirective) {
3127 for (auto &Feature : RISCVFeatureKV)
3129 clearFeatureBits(Feature.Value, Feature.Key);
3130
3131 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
3132 Arch, /*EnableExperimentalExtension=*/true,
3133 /*ExperimentalExtensionVersionCheck=*/true);
3134 if (!ParseResult) {
3135 std::string Buffer;
3136 raw_string_ostream OutputErrMsg(Buffer);
3137 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
3138 OutputErrMsg << "invalid arch name '" << Arch << "', "
3139 << ErrMsg.getMessage();
3140 });
3141
3142 return Error(Loc, OutputErrMsg.str());
3143 }
3144 auto &ISAInfo = *ParseResult;
3145
3146 for (auto &Feature : RISCVFeatureKV)
3147 if (ISAInfo->hasExtension(Feature.Key))
3148 setFeatureBits(Feature.Value, Feature.Key);
3149
3150 if (FromOptionDirective) {
3151 if (ISAInfo->getXLen() == 32 && isRV64())
3152 return Error(Loc, "bad arch string switching from rv64 to rv32");
3153 else if (ISAInfo->getXLen() == 64 && !isRV64())
3154 return Error(Loc, "bad arch string switching from rv32 to rv64");
3155 }
3156
3157 if (ISAInfo->getXLen() == 32)
3158 clearFeatureBits(RISCV::Feature64Bit, "64bit");
3159 else if (ISAInfo->getXLen() == 64)
3160 setFeatureBits(RISCV::Feature64Bit, "64bit");
3161 else
3162 return Error(Loc, "bad arch string " + Arch);
3163
3164 Result = ISAInfo->toString();
3165 return false;
3166}
3167
3168bool RISCVAsmParser::parseDirectiveOption() {
3169 MCAsmParser &Parser = getParser();
3170 // Get the option token.
3171 AsmToken Tok = Parser.getTok();
3172
3173 // At the moment only identifiers are supported.
3174 if (parseToken(AsmToken::Identifier, "expected identifier"))
3175 return true;
3176
3177 StringRef Option = Tok.getIdentifier();
3178
3179 if (Option == "push") {
3180 if (Parser.parseEOL())
3181 return true;
3182
3183 getTargetStreamer().emitDirectiveOptionPush();
3184 pushFeatureBits();
3185 return false;
3186 }
3187
3188 if (Option == "pop") {
3189 SMLoc StartLoc = Parser.getTok().getLoc();
3190 if (Parser.parseEOL())
3191 return true;
3192
3193 getTargetStreamer().emitDirectiveOptionPop();
3194 if (popFeatureBits())
3195 return Error(StartLoc, ".option pop with no .option push");
3196
3197 return false;
3198 }
3199
3200 if (Option == "arch") {
3202 do {
3203 if (Parser.parseComma())
3204 return true;
3205
3207 if (parseOptionalToken(AsmToken::Plus))
3208 Type = RISCVOptionArchArgType::Plus;
3209 else if (parseOptionalToken(AsmToken::Minus))
3210 Type = RISCVOptionArchArgType::Minus;
3211 else if (!Args.empty())
3212 return Error(Parser.getTok().getLoc(),
3213 "unexpected token, expected + or -");
3214 else
3215 Type = RISCVOptionArchArgType::Full;
3216
3217 if (Parser.getTok().isNot(AsmToken::Identifier))
3218 return Error(Parser.getTok().getLoc(),
3219 "unexpected token, expected identifier");
3220
3221 StringRef Arch = Parser.getTok().getString();
3222 SMLoc Loc = Parser.getTok().getLoc();
3223 Parser.Lex();
3224
3225 if (Type == RISCVOptionArchArgType::Full) {
3226 std::string Result;
3227 if (resetToArch(Arch, Loc, Result, true))
3228 return true;
3229
3230 Args.emplace_back(Type, Result);
3231 break;
3232 }
3233
3234 if (isDigit(Arch.back()))
3235 return Error(
3236 Loc, "extension version number parsing not currently implemented");
3237
3238 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
3239 if (!enableExperimentalExtension() &&
3240 StringRef(Feature).starts_with("experimental-"))
3241 return Error(Loc, "unexpected experimental extensions");
3242 auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);
3243 if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)
3244 return Error(Loc, "unknown extension feature");
3245
3246 Args.emplace_back(Type, Arch.str());
3247
3248 if (Type == RISCVOptionArchArgType::Plus) {
3249 FeatureBitset OldFeatureBits = STI->getFeatureBits();
3250
3251 setFeatureBits(Ext->Value, Ext->Key);
3252 auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());
3253 if (!ParseResult) {
3254 copySTI().setFeatureBits(OldFeatureBits);
3255 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3256
3257 std::string Buffer;
3258 raw_string_ostream OutputErrMsg(Buffer);
3259 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
3260 OutputErrMsg << ErrMsg.getMessage();
3261 });
3262
3263 return Error(Loc, OutputErrMsg.str());
3264 }
3265 } else {
3266 assert(Type == RISCVOptionArchArgType::Minus);
3267 // It is invalid to disable an extension that there are other enabled
3268 // extensions depend on it.
3269 // TODO: Make use of RISCVISAInfo to handle this
3270 for (auto &Feature : RISCVFeatureKV) {
3271 if (getSTI().hasFeature(Feature.Value) &&
3272 Feature.Implies.test(Ext->Value))
3273 return Error(Loc, Twine("can't disable ") + Ext->Key +
3274 " extension; " + Feature.Key +
3275 " extension requires " + Ext->Key +
3276 " extension");
3277 }
3278
3279 clearFeatureBits(Ext->Value, Ext->Key);
3280 }
3281 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
3282
3283 if (Parser.parseEOL())
3284 return true;
3285
3286 getTargetStreamer().emitDirectiveOptionArch(Args);
3287
3288 if (auto ParseResult =
3290 getTargetStreamer().setArchString((*ParseResult)->toString());
3291 return false;
3292 }
3293
3294 if (Option == "exact") {
3295 if (Parser.parseEOL())
3296 return true;
3297
3298 getTargetStreamer().emitDirectiveOptionExact();
3299 setFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
3300 clearFeatureBits(RISCV::FeatureRelax, "relax");
3301 return false;
3302 }
3303
3304 if (Option == "noexact") {
3305 if (Parser.parseEOL())
3306 return true;
3307
3308 getTargetStreamer().emitDirectiveOptionNoExact();
3309 clearFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
3310 setFeatureBits(RISCV::FeatureRelax, "relax");
3311 return false;
3312 }
3313
3314 if (Option == "rvc") {
3315 if (Parser.parseEOL())
3316 return true;
3317
3318 getTargetStreamer().emitDirectiveOptionRVC();
3319 setFeatureBits(RISCV::FeatureStdExtC, "c");
3320 if (auto ParseResult =
3322 getTargetStreamer().setArchString((*ParseResult)->toString());
3323 return false;
3324 }
3325
3326 if (Option == "norvc") {
3327 if (Parser.parseEOL())
3328 return true;
3329
3330 getTargetStreamer().emitDirectiveOptionNoRVC();
3331 clearFeatureBits(RISCV::FeatureStdExtC, "c");
3332 clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
3333 if (auto ParseResult =
3335 getTargetStreamer().setArchString((*ParseResult)->toString());
3336 return false;
3337 }
3338
3339 if (Option == "pic") {
3340 if (Parser.parseEOL())
3341 return true;
3342
3343 getTargetStreamer().emitDirectiveOptionPIC();
3344 ParserOptions.IsPicEnabled = true;
3345 return false;
3346 }
3347
3348 if (Option == "nopic") {
3349 if (Parser.parseEOL())
3350 return true;
3351
3352 getTargetStreamer().emitDirectiveOptionNoPIC();
3353 ParserOptions.IsPicEnabled = false;
3354 return false;
3355 }
3356
3357 if (Option == "relax") {
3358 if (Parser.parseEOL())
3359 return true;
3360
3361 getTargetStreamer().emitDirectiveOptionRelax();
3362 setFeatureBits(RISCV::FeatureRelax, "relax");
3363 return false;
3364 }
3365
3366 if (Option == "norelax") {
3367 if (Parser.parseEOL())
3368 return true;
3369
3370 getTargetStreamer().emitDirectiveOptionNoRelax();
3371 clearFeatureBits(RISCV::FeatureRelax, "relax");
3372 return false;
3373 }
3374
3375 // Unknown option.
3376 Warning(Parser.getTok().getLoc(),
3377 "unknown option, expected 'push', 'pop', "
3378 "'rvc', 'norvc', 'arch', 'relax', 'norelax', "
3379 "'exact', or 'noexact'");
3380 Parser.eatToEndOfStatement();
3381 return false;
3382}
3383
3384/// parseDirectiveAttribute
3385/// ::= .attribute expression ',' ( expression | "string" )
3386/// ::= .attribute identifier ',' ( expression | "string" )
3387bool RISCVAsmParser::parseDirectiveAttribute() {
3388 MCAsmParser &Parser = getParser();
3389 int64_t Tag;
3390 SMLoc TagLoc;
3391 TagLoc = Parser.getTok().getLoc();
3392 if (Parser.getTok().is(AsmToken::Identifier)) {
3393 StringRef Name = Parser.getTok().getIdentifier();
3394 std::optional<unsigned> Ret =
3396 if (!Ret)
3397 return Error(TagLoc, "attribute name not recognised: " + Name);
3398 Tag = *Ret;
3399 Parser.Lex();
3400 } else {
3401 const MCExpr *AttrExpr;
3402
3403 TagLoc = Parser.getTok().getLoc();
3404 if (Parser.parseExpression(AttrExpr))
3405 return true;
3406
3407 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
3408 if (check(!CE, TagLoc, "expected numeric constant"))
3409 return true;
3410
3411 Tag = CE->getValue();
3412 }
3413
3414 if (Parser.parseComma())
3415 return true;
3416
3417 StringRef StringValue;
3418 int64_t IntegerValue = 0;
3419 bool IsIntegerValue = true;
3420
3421 // RISC-V attributes have a string value if the tag number is odd
3422 // and an integer value if the tag number is even.
3423 if (Tag % 2)
3424 IsIntegerValue = false;
3425
3426 SMLoc ValueExprLoc = Parser.getTok().getLoc();
3427 if (IsIntegerValue) {
3428 const MCExpr *ValueExpr;
3429 if (Parser.parseExpression(ValueExpr))
3430 return true;
3431
3432 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
3433 if (!CE)
3434 return Error(ValueExprLoc, "expected numeric constant");
3435 IntegerValue = CE->getValue();
3436 } else {
3437 if (Parser.getTok().isNot(AsmToken::String))
3438 return Error(Parser.getTok().getLoc(), "expected string constant");
3439
3440 StringValue = Parser.getTok().getStringContents();
3441 Parser.Lex();
3442 }
3443
3444 if (Parser.parseEOL())
3445 return true;
3446
3447 if (IsIntegerValue)
3448 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3449 else if (Tag != RISCVAttrs::ARCH)
3450 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3451 else {
3452 std::string Result;
3453 if (resetToArch(StringValue, ValueExprLoc, Result, false))
3454 return true;
3455
3456 // Then emit the arch string.
3457 getTargetStreamer().emitTextAttribute(Tag, Result);
3458
3459 // And then update the active ISA so the next instruction-run emits
3460 // an ISA-specific mapping symbol.
3461 getTargetStreamer().setArchString(Result);
3462 }
3463
3464 return false;
3465}
3466
3468 return StringSwitch<bool>(Format)
3469 .Cases({"r", "r4", "i", "b", "sb", "u", "j", "uj", "s"}, true)
3470 .Cases({"cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj"},
3471 STI.hasFeature(RISCV::FeatureStdExtZca))
3472 .Cases({"qc.eai", "qc.ei", "qc.eb", "qc.ej", "qc.es"},
3473 !STI.hasFeature(RISCV::Feature64Bit))
3474 .Default(false);
3475}
3476
3477/// parseDirectiveInsn
3478/// ::= .insn [ format encoding, (operands (, operands)*) ]
3479/// ::= .insn [ length, value ]
3480/// ::= .insn [ value ]
3481bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3482 MCAsmParser &Parser = getParser();
3483
3484 // Expect instruction format as identifier.
3485 StringRef Format;
3486 SMLoc ErrorLoc = Parser.getTok().getLoc();
3487 if (Parser.parseIdentifier(Format)) {
3488 // Try parsing .insn [ length , ] value
3489 std::optional<int64_t> Length;
3490 int64_t Value = 0;
3491 if (Parser.parseAbsoluteExpression(Value))
3492 return true;
3493 if (Parser.parseOptionalToken(AsmToken::Comma)) {
3494 Length = Value;
3495 if (Parser.parseAbsoluteExpression(Value))
3496 return true;
3497
3498 if (*Length == 0 || (*Length % 2) != 0)
3499 return Error(ErrorLoc,
3500 "instruction lengths must be a non-zero multiple of two");
3501
3502 // TODO: Support Instructions > 64 bits.
3503 if (*Length > 8)
3504 return Error(ErrorLoc,
3505 "instruction lengths over 64 bits are not supported");
3506 }
3507
3508 // We only derive a length from the encoding for 16- and 32-bit
3509 // instructions, as the encodings for longer instructions are not frozen in
3510 // the spec.
3511 int64_t EncodingDerivedLength = ((Value & 0b11) == 0b11) ? 4 : 2;
3512
3513 if (Length) {
3514 // Only check the length against the encoding if the length is present and
3515 // could match
3516 if ((*Length <= 4) && (*Length != EncodingDerivedLength))
3517 return Error(ErrorLoc,
3518 "instruction length does not match the encoding");
3519
3520 if (!isUIntN(*Length * 8, Value))
3521 return Error(ErrorLoc, "encoding value does not fit into instruction");
3522 } else {
3523 if (!isUIntN(EncodingDerivedLength * 8, Value))
3524 return Error(ErrorLoc, "encoding value does not fit into instruction");
3525 }
3526
3527 if (!getSTI().hasFeature(RISCV::FeatureStdExtZca) &&
3528 (EncodingDerivedLength == 2))
3529 return Error(ErrorLoc, "compressed instructions are not allowed");
3530
3531 if (getParser().parseEOL("invalid operand for instruction")) {
3532 getParser().eatToEndOfStatement();
3533 return true;
3534 }
3535
3536 unsigned Opcode;
3537 if (Length) {
3538 switch (*Length) {
3539 case 2:
3540 Opcode = RISCV::Insn16;
3541 break;
3542 case 4:
3543 Opcode = RISCV::Insn32;
3544 break;
3545 case 6:
3546 Opcode = RISCV::Insn48;
3547 break;
3548 case 8:
3549 Opcode = RISCV::Insn64;
3550 break;
3551 default:
3552 llvm_unreachable("Error should have already been emitted");
3553 }
3554 } else
3555 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3556
3557 emitToStreamer(getStreamer(), MCInstBuilder(Opcode).addImm(Value));
3558 return false;
3559 }
3560
3561 if (!isValidInsnFormat(Format, getSTI()))
3562 return Error(ErrorLoc, "invalid instruction format");
3563
3564 std::string FormatName = (".insn_" + Format).str();
3565
3566 ParseInstructionInfo Info;
3568
3569 if (parseInstruction(Info, FormatName, L, Operands))
3570 return true;
3571
3572 unsigned Opcode;
3573 uint64_t ErrorInfo;
3574 return matchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3575 ErrorInfo,
3576 /*MatchingInlineAsm=*/false);
3577}
3578
3579/// parseDirectiveVariantCC
3580/// ::= .variant_cc symbol
3581bool RISCVAsmParser::parseDirectiveVariantCC() {
3582 StringRef Name;
3583 if (getParser().parseIdentifier(Name))
3584 return TokError("expected symbol name");
3585 if (parseEOL())
3586 return true;
3587 getTargetStreamer().emitDirectiveVariantCC(
3588 *getContext().getOrCreateSymbol(Name));
3589 return false;
3590}
3591
3592void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3593 MCInst CInst;
3594 bool Res = false;
3595 const MCSubtargetInfo &STI = getSTI();
3596 if (!STI.hasFeature(RISCV::FeatureExactAssembly))
3597 Res = RISCVRVC::compress(CInst, Inst, STI);
3598 if (Res)
3599 ++RISCVNumInstrsCompressed;
3600 S.emitInstruction((Res ? CInst : Inst), STI);
3601}
3602
3603void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3604 MCStreamer &Out) {
3606 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
3607
3608 for (MCInst &Inst : Seq) {
3609 emitToStreamer(Out, Inst);
3610 }
3611}
3612
3613void RISCVAsmParser::emitAuipcInstPair(MCRegister DestReg, MCRegister TmpReg,
3614 const MCExpr *Symbol,
3615 RISCV::Specifier VKHi,
3616 unsigned SecondOpcode, SMLoc IDLoc,
3617 MCStreamer &Out) {
3618 // A pair of instructions for PC-relative addressing; expands to
3619 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3620 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3621 MCContext &Ctx = getContext();
3622
3623 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3624 Out.emitLabel(TmpLabel);
3625
3626 const auto *SymbolHi = MCSpecifierExpr::create(Symbol, VKHi, Ctx);
3627 emitToStreamer(Out,
3628 MCInstBuilder(RISCV::AUIPC).addReg(TmpReg).addExpr(SymbolHi));
3629
3630 const MCExpr *RefToLinkTmpLabel = MCSpecifierExpr::create(
3631 MCSymbolRefExpr::create(TmpLabel, Ctx), RISCV::S_PCREL_LO, Ctx);
3632
3633 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3634 .addReg(DestReg)
3635 .addReg(TmpReg)
3636 .addExpr(RefToLinkTmpLabel));
3637}
3638
3639void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3640 MCStreamer &Out) {
3641 // The load local address pseudo-instruction "lla" is used in PC-relative
3642 // addressing of local symbols:
3643 // lla rdest, symbol
3644 // expands to
3645 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3646 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3647 MCRegister DestReg = Inst.getOperand(0).getReg();
3648 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3649 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCV::S_PCREL_HI, RISCV::ADDI,
3650 IDLoc, Out);
3651}
3652
3653void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3654 MCStreamer &Out) {
3655 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3656 // addressing of global symbols:
3657 // lga rdest, symbol
3658 // expands to
3659 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3660 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3661 MCRegister DestReg = Inst.getOperand(0).getReg();
3662 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3663 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3664 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCV::S_GOT_HI, SecondOpcode,
3665 IDLoc, Out);
3666}
3667
3668void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3669 MCStreamer &Out) {
3670 // The load address pseudo-instruction "la" is used in PC-relative and
3671 // GOT-indirect addressing of global symbols:
3672 // la rdest, symbol
3673 // is an alias for either (for non-PIC)
3674 // lla rdest, symbol
3675 // or (for PIC)
3676 // lga rdest, symbol
3677 if (ParserOptions.IsPicEnabled)
3678 emitLoadGlobalAddress(Inst, IDLoc, Out);
3679 else
3680 emitLoadLocalAddress(Inst, IDLoc, Out);
3681}
3682
3683void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3684 MCStreamer &Out) {
3685 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3686 // initial-exec TLS model addressing of global symbols:
3687 // la.tls.ie rdest, symbol
3688 // expands to
3689 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3690 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3691 MCRegister DestReg = Inst.getOperand(0).getReg();
3692 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3693 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3694 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GOT_HI20,
3695 SecondOpcode, IDLoc, Out);
3696}
3697
3698void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3699 MCStreamer &Out) {
3700 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3701 // global-dynamic TLS model addressing of global symbols:
3702 // la.tls.gd rdest, symbol
3703 // expands to
3704 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3705 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3706 MCRegister DestReg = Inst.getOperand(0).getReg();
3707 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3708 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GD_HI20,
3709 RISCV::ADDI, IDLoc, Out);
3710}
3711
3712void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3713 SMLoc IDLoc, MCStreamer &Out,
3714 bool HasTmpReg) {
3715 // The load/store pseudo-instruction does a pc-relative load with
3716 // a symbol.
3717 //
3718 // The expansion looks like this
3719 //
3720 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3721 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3722 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3723 MCRegister DestReg = Inst.getOperand(DestRegOpIdx).getReg();
3724 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3725 MCRegister TmpReg = Inst.getOperand(0).getReg();
3726
3727 // If TmpReg is a GPR pair, get the even register.
3728 if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(TmpReg)) {
3729 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3730 TmpReg = RI->getSubReg(TmpReg, RISCV::sub_gpr_even);
3731 }
3732
3733 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3734 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCV::S_PCREL_HI, Opcode, IDLoc,
3735 Out);
3736}
3737
3738void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3739 int64_t Width, SMLoc IDLoc,
3740 MCStreamer &Out) {
3741 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3742 // amounts dependent on the XLEN.
3743 //
3744 // The expansion looks like this
3745 //
3746 // SLLI rd, rs, XLEN - Width
3747 // SR[A|R]I rd, rd, XLEN - Width
3748 const MCOperand &DestReg = Inst.getOperand(0);
3749 const MCOperand &SourceReg = Inst.getOperand(1);
3750
3751 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3752 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3753
3754 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3755
3756 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3757 .addOperand(DestReg)
3758 .addOperand(SourceReg)
3759 .addImm(ShAmt));
3760
3761 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3762 .addOperand(DestReg)
3763 .addOperand(DestReg)
3764 .addImm(ShAmt));
3765}
3766
3767void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3768 MCStreamer &Out) {
3769 if (Inst.getNumOperands() == 3) {
3770 // unmasked va >= x
3771 //
3772 // pseudoinstruction: vmsge{u}.vx vd, va, x
3773 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3774 emitToStreamer(Out, MCInstBuilder(Opcode)
3775 .addOperand(Inst.getOperand(0))
3776 .addOperand(Inst.getOperand(1))
3777 .addOperand(Inst.getOperand(2))
3778 .addReg(MCRegister())
3779 .setLoc(IDLoc));
3780 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3781 .addOperand(Inst.getOperand(0))
3782 .addOperand(Inst.getOperand(0))
3783 .addOperand(Inst.getOperand(0))
3784 .setLoc(IDLoc));
3785 } else if (Inst.getNumOperands() == 4) {
3786 // masked va >= x, vd != v0
3787 //
3788 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3789 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3790 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3791 "The destination register should not be V0.");
3792 emitToStreamer(Out, MCInstBuilder(Opcode)
3793 .addOperand(Inst.getOperand(0))
3794 .addOperand(Inst.getOperand(1))
3795 .addOperand(Inst.getOperand(2))
3796 .addOperand(Inst.getOperand(3))
3797 .setLoc(IDLoc));
3798 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3799 .addOperand(Inst.getOperand(0))
3800 .addOperand(Inst.getOperand(0))
3801 .addReg(RISCV::V0)
3802 .setLoc(IDLoc));
3803 } else if (Inst.getNumOperands() == 5 &&
3804 Inst.getOperand(0).getReg() == RISCV::V0) {
3805 // masked va >= x, vd == v0
3806 //
3807 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3808 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3809 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3810 "The destination register should be V0.");
3811 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3812 "The temporary vector register should not be V0.");
3813 emitToStreamer(Out, MCInstBuilder(Opcode)
3814 .addOperand(Inst.getOperand(1))
3815 .addOperand(Inst.getOperand(2))
3816 .addOperand(Inst.getOperand(3))
3817 .addReg(MCRegister())
3818 .setLoc(IDLoc));
3819 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3820 .addOperand(Inst.getOperand(0))
3821 .addOperand(Inst.getOperand(0))
3822 .addOperand(Inst.getOperand(1))
3823 .setLoc(IDLoc));
3824 } else if (Inst.getNumOperands() == 5) {
3825 // masked va >= x, any vd
3826 //
3827 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3828 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3829 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3830 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3831 "The temporary vector register should not be V0.");
3832 emitToStreamer(Out, MCInstBuilder(Opcode)
3833 .addOperand(Inst.getOperand(1))
3834 .addOperand(Inst.getOperand(2))
3835 .addOperand(Inst.getOperand(3))
3836 .addReg(MCRegister())
3837 .setLoc(IDLoc));
3838 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3839 .addOperand(Inst.getOperand(1))
3840 .addReg(RISCV::V0)
3841 .addOperand(Inst.getOperand(1))
3842 .setLoc(IDLoc));
3843 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3844 .addOperand(Inst.getOperand(0))
3845 .addOperand(Inst.getOperand(0))
3846 .addReg(RISCV::V0)
3847 .setLoc(IDLoc));
3848 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3849 .addOperand(Inst.getOperand(0))
3850 .addOperand(Inst.getOperand(1))
3851 .addOperand(Inst.getOperand(0))
3852 .setLoc(IDLoc));
3853 }
3854}
3855
3856bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3857 OperandVector &Operands) {
3858 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
3859 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
3860 if (Inst.getOperand(2).getReg() != RISCV::X4) {
3861 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3862 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
3863 "%tprel_add specifier");
3864 }
3865
3866 return false;
3867}
3868
3869bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
3870 OperandVector &Operands) {
3871 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
3872 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
3873 if (Inst.getOperand(0).getReg() != RISCV::X5) {
3874 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3875 return Error(ErrorLoc, "the output operand must be t0/x5 when using "
3876 "%tlsdesc_call specifier");
3877 }
3878
3879 return false;
3880}
3881
3882std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3883 return RISCVOperand::createReg(MCRegister(), llvm::SMLoc(), llvm::SMLoc());
3884}
3885
3886std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3887 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3888 llvm::SMLoc());
3889}
3890
3891std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3892 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3893 llvm::SMLoc());
3894}
3895
3896static unsigned getNFforLXSEG(unsigned Opcode) {
3897 switch (Opcode) {
3898 default:
3899 return 1;
3900 case RISCV::VLOXSEG2EI8_V:
3901 case RISCV::VLOXSEG2EI16_V:
3902 case RISCV::VLOXSEG2EI32_V:
3903 case RISCV::VLOXSEG2EI64_V:
3904 case RISCV::VLUXSEG2EI8_V:
3905 case RISCV::VLUXSEG2EI16_V:
3906 case RISCV::VLUXSEG2EI32_V:
3907 case RISCV::VLUXSEG2EI64_V:
3908 return 2;
3909 case RISCV::VLOXSEG3EI8_V:
3910 case RISCV::VLOXSEG3EI16_V:
3911 case RISCV::VLOXSEG3EI32_V:
3912 case RISCV::VLOXSEG3EI64_V:
3913 case RISCV::VLUXSEG3EI8_V:
3914 case RISCV::VLUXSEG3EI16_V:
3915 case RISCV::VLUXSEG3EI32_V:
3916 case RISCV::VLUXSEG3EI64_V:
3917 return 3;
3918 case RISCV::VLOXSEG4EI8_V:
3919 case RISCV::VLOXSEG4EI16_V:
3920 case RISCV::VLOXSEG4EI32_V:
3921 case RISCV::VLOXSEG4EI64_V:
3922 case RISCV::VLUXSEG4EI8_V:
3923 case RISCV::VLUXSEG4EI16_V:
3924 case RISCV::VLUXSEG4EI32_V:
3925 case RISCV::VLUXSEG4EI64_V:
3926 return 4;
3927 case RISCV::VLOXSEG5EI8_V:
3928 case RISCV::VLOXSEG5EI16_V:
3929 case RISCV::VLOXSEG5EI32_V:
3930 case RISCV::VLOXSEG5EI64_V:
3931 case RISCV::VLUXSEG5EI8_V:
3932 case RISCV::VLUXSEG5EI16_V:
3933 case RISCV::VLUXSEG5EI32_V:
3934 case RISCV::VLUXSEG5EI64_V:
3935 return 5;
3936 case RISCV::VLOXSEG6EI8_V:
3937 case RISCV::VLOXSEG6EI16_V:
3938 case RISCV::VLOXSEG6EI32_V:
3939 case RISCV::VLOXSEG6EI64_V:
3940 case RISCV::VLUXSEG6EI8_V:
3941 case RISCV::VLUXSEG6EI16_V:
3942 case RISCV::VLUXSEG6EI32_V:
3943 case RISCV::VLUXSEG6EI64_V:
3944 return 6;
3945 case RISCV::VLOXSEG7EI8_V:
3946 case RISCV::VLOXSEG7EI16_V:
3947 case RISCV::VLOXSEG7EI32_V:
3948 case RISCV::VLOXSEG7EI64_V:
3949 case RISCV::VLUXSEG7EI8_V:
3950 case RISCV::VLUXSEG7EI16_V:
3951 case RISCV::VLUXSEG7EI32_V:
3952 case RISCV::VLUXSEG7EI64_V:
3953 return 7;
3954 case RISCV::VLOXSEG8EI8_V:
3955 case RISCV::VLOXSEG8EI16_V:
3956 case RISCV::VLOXSEG8EI32_V:
3957 case RISCV::VLOXSEG8EI64_V:
3958 case RISCV::VLUXSEG8EI8_V:
3959 case RISCV::VLUXSEG8EI16_V:
3960 case RISCV::VLUXSEG8EI32_V:
3961 case RISCV::VLUXSEG8EI64_V:
3962 return 8;
3963 }
3964}
3965
3967 if (RISCVMCRegisterClasses[RISCV::VRM2RegClassID].contains(Reg))
3968 return 2;
3969 if (RISCVMCRegisterClasses[RISCV::VRM4RegClassID].contains(Reg))
3970 return 4;
3971 if (RISCVMCRegisterClasses[RISCV::VRM8RegClassID].contains(Reg))
3972 return 8;
3973 return 1;
3974}
3975
3976static bool isZvvfmmScaleOpcode(unsigned Opcode) {
3977 switch (Opcode) {
3978 case RISCV::VFWMMACC_VV_SCALE:
3979 case RISCV::VFQMMACC_VV_SCALE:
3980 case RISCV::VF8WMMACC_VV_SCALE:
3981 case RISCV::VFWIMMACC_VV:
3982 case RISCV::VFQIMMACC_VV:
3983 case RISCV::VF8WIMMACC_VV:
3984 return true;
3985 default:
3986 return false;
3987 }
3988}
3989
3990bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3991 OperandVector &Operands) {
3992 unsigned Opcode = Inst.getOpcode();
3993
3994 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3995 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3996 MCRegister DestReg = Inst.getOperand(0).getReg();
3997 MCRegister TempReg = Inst.getOperand(1).getReg();
3998 if (DestReg == TempReg) {
3999 SMLoc Loc = Operands.back()->getStartLoc();
4000 return Error(Loc, "the temporary vector register cannot be the same as "
4001 "the destination register");
4002 }
4003 }
4004
4005 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
4006 Opcode == RISCV::TH_LWD) {
4007 MCRegister Rd1 = Inst.getOperand(0).getReg();
4008 MCRegister Rd2 = Inst.getOperand(1).getReg();
4009 MCRegister Rs1 = Inst.getOperand(2).getReg();
4010 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
4011 if (Rs1 == Rd1 || Rs1 == Rd2 || Rd1 == Rd2) {
4012 SMLoc Loc = Operands[1]->getStartLoc();
4013 return Error(Loc, "rs1, rd1, and rd2 cannot overlap");
4014 }
4015 }
4016
4017 if (Opcode == RISCV::CM_MVSA01 || Opcode == RISCV::QC_CM_MVSA01) {
4018 MCRegister Rs1 = Inst.getOperand(0).getReg();
4019 MCRegister Rs2 = Inst.getOperand(1).getReg();
4020 if (Rs1 == Rs2) {
4021 SMLoc Loc = Operands[1]->getStartLoc();
4022 return Error(Loc, "rs1 and rs2 must be different");
4023 }
4024 }
4025
4026 if (isZvvfmmScaleOpcode(Opcode)) {
4027 auto CheckOperandDoesNotOverlapV0 = [&](int OperandIdx,
4028 unsigned ParsedIdx) {
4029 if (Inst.getOperand(OperandIdx).getReg() == RISCV::V0)
4030 return Error(Operands[ParsedIdx]->getStartLoc(),
4031 "vd, vs1, and vs2 cannot overlap v0.scale");
4032 return false;
4033 };
4034
4035 int DestIdx =
4036 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
4037 int VS1Idx =
4038 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
4039 int VS2Idx =
4040 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
4041 assert(DestIdx >= 0 && VS1Idx >= 0 && VS2Idx >= 0 &&
4042 "Unexpected Zvvfmm scaled operand list");
4043
4044 if (CheckOperandDoesNotOverlapV0(DestIdx, 1) ||
4045 CheckOperandDoesNotOverlapV0(VS1Idx, 2) ||
4046 CheckOperandDoesNotOverlapV0(VS2Idx, 3))
4047 return true;
4048 }
4049
4050 const MCInstrDesc &MCID = MII.get(Opcode);
4051 if (!(MCID.TSFlags & RISCVII::RVVConstraintMask))
4052 return false;
4053
4054 int DestIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
4055 MCRegister DestReg = Inst.getOperand(DestIdx).getReg();
4056
4057 // Operands[1] or Operands[2] will be the first operand, DestReg.
4058 const MCParsedAsmOperand *ParsedOp = Operands[1].get();
4059 if (!ParsedOp->isReg()) {
4060 // XSfvcp instructions may have an immediate before vd.
4061 // FIXME: Is there a better way to do this?
4062 ParsedOp = Operands[2].get();
4063 }
4064 assert(ParsedOp->getReg() == DestReg && "Can't find parsed dest operand");
4065 SMLoc Loc = ParsedOp->getStartLoc();
4066
4067 unsigned Lmul = getLMULFromVectorRegister(DestReg);
4068 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4069 unsigned DestEncoding = RI->getEncodingValue(DestReg);
4070 if (MCID.TSFlags & RISCVII::VS2Constraint) {
4071 int VS2Idx =
4072 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
4073 assert(VS2Idx >= 0 && "No vs2 operand?");
4074 unsigned CheckEncoding =
4075 RI->getEncodingValue(Inst.getOperand(VS2Idx).getReg());
4076 unsigned NF = getNFforLXSEG(Opcode);
4077 for (unsigned i = 0; i < std::max(NF, Lmul); i++) {
4078 if ((DestEncoding + i) == CheckEncoding)
4079 return Error(Loc, "the destination vector register group cannot overlap"
4080 " the source vector register group");
4081 }
4082 }
4083 if (MCID.TSFlags & RISCVII::VS1Constraint) {
4084 int VS1Idx =
4085 RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
4086 // FIXME: The vs1 constraint is used on scalar and imm instructions so we
4087 // need to check that the operand exists.
4088 if (VS1Idx >= 0) {
4089 unsigned CheckEncoding =
4090 RI->getEncodingValue(Inst.getOperand(VS1Idx).getReg());
4091 for (unsigned i = 0; i < Lmul; i++) {
4092 if ((DestEncoding + i) == CheckEncoding)
4093 return Error(Loc,
4094 "the destination vector register group cannot overlap"
4095 " the source vector register group");
4096 }
4097 }
4098 }
4099
4100 if (MCID.TSFlags & RISCVII::VMConstraint) {
4101 int VMIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vm);
4102 assert(VMIdx >= 0 && "No vm operand?");
4103
4104 if (DestReg == RISCV::V0) {
4105 if (MCID.operands()[Inst.getNumOperands() - 1].OperandType !=
4107 return Error(Loc, "the destination vector register group cannot be V0");
4108
4109 // Regardless masked or unmasked version, the number of operands is the
4110 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
4111 // actually. We need to check the operand to see whether it is masked or
4112 // not.
4113 MCRegister CheckReg = Inst.getOperand(VMIdx).getReg();
4114 assert((!CheckReg.isValid() || CheckReg == RISCV::V0) &&
4115 "Unexpected mask operand register");
4116 if (CheckReg.isValid())
4117 return Error(Loc, "the destination vector register group cannot overlap"
4118 " the mask register");
4119 }
4120 }
4121
4122 return false;
4123}
4124
4125bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
4126 OperandVector &Operands,
4127 MCStreamer &Out) {
4128 Inst.setLoc(IDLoc);
4129
4130 switch (Inst.getOpcode()) {
4131 default:
4132 break;
4133 case RISCV::PseudoC_ADDI_NOP: {
4134 if (Inst.getOperand(2).getImm() == 0)
4135 emitToStreamer(Out, MCInstBuilder(RISCV::C_NOP));
4136 else
4137 emitToStreamer(
4138 Out, MCInstBuilder(RISCV::C_NOP_HINT).addOperand(Inst.getOperand(2)));
4139 return false;
4140 }
4141 case RISCV::PACK: {
4142 // Convert PACK wth RS2==X0 to ZEXT_H_RV32 to match disassembler output.
4143 if (Inst.getOperand(2).getReg() != RISCV::X0)
4144 break;
4145 if (getSTI().hasFeature(RISCV::Feature64Bit))
4146 break;
4147 emitToStreamer(Out, MCInstBuilder(RISCV::ZEXT_H_RV32)
4148 .addOperand(Inst.getOperand(0))
4149 .addOperand(Inst.getOperand(1)));
4150 return false;
4151 }
4152 case RISCV::PACKW: {
4153 // Convert PACKW with RS2==X0 to ZEXT_H_RV64 to match disassembler output.
4154 if (Inst.getOperand(2).getReg() != RISCV::X0)
4155 break;
4156 emitToStreamer(Out, MCInstBuilder(RISCV::ZEXT_H_RV64)
4157 .addOperand(Inst.getOperand(0))
4158 .addOperand(Inst.getOperand(1)));
4159 return false;
4160 }
4161 case RISCV::PseudoLLAImm:
4162 case RISCV::PseudoLAImm:
4163 case RISCV::PseudoLI: {
4164 MCRegister Reg = Inst.getOperand(0).getReg();
4165 const MCOperand &Op1 = Inst.getOperand(1);
4166 if (Op1.isExpr()) {
4167 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
4168 // Just convert to an addi. This allows compatibility with gas.
4169 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
4170 .addReg(Reg)
4171 .addReg(RISCV::X0)
4172 .addExpr(Op1.getExpr()));
4173 return false;
4174 }
4175 int64_t Imm = Inst.getOperand(1).getImm();
4176 // On RV32 the immediate here can either be a signed or an unsigned
4177 // 32-bit number. Sign extension has to be performed to ensure that Imm
4178 // represents the expected signed 64-bit number.
4179 if (!isRV64())
4180 Imm = SignExtend64<32>(Imm);
4181 emitLoadImm(Reg, Imm, Out);
4182 return false;
4183 }
4184 case RISCV::PseudoLLA:
4185 emitLoadLocalAddress(Inst, IDLoc, Out);
4186 return false;
4187 case RISCV::PseudoLGA:
4188 emitLoadGlobalAddress(Inst, IDLoc, Out);
4189 return false;
4190 case RISCV::PseudoLA:
4191 emitLoadAddress(Inst, IDLoc, Out);
4192 return false;
4193 case RISCV::PseudoLA_TLS_IE:
4194 emitLoadTLSIEAddress(Inst, IDLoc, Out);
4195 return false;
4196 case RISCV::PseudoLA_TLS_GD:
4197 emitLoadTLSGDAddress(Inst, IDLoc, Out);
4198 return false;
4199 case RISCV::PseudoLB:
4200 case RISCV::PseudoQC_E_LB:
4201 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
4202 return false;
4203 case RISCV::PseudoLBU:
4204 case RISCV::PseudoQC_E_LBU:
4205 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
4206 return false;
4207 case RISCV::PseudoLH:
4208 case RISCV::PseudoQC_E_LH:
4209 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
4210 return false;
4211 case RISCV::PseudoLHU:
4212 case RISCV::PseudoQC_E_LHU:
4213 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
4214 return false;
4215 case RISCV::PseudoLW:
4216 case RISCV::PseudoQC_E_LW:
4217 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
4218 return false;
4219 case RISCV::PseudoLWU:
4220 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
4221 return false;
4222 case RISCV::PseudoLD:
4223 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
4224 return false;
4225 case RISCV::PseudoLD_RV32:
4226 emitLoadStoreSymbol(Inst, RISCV::LD_RV32, IDLoc, Out, /*HasTmpReg=*/false);
4227 return false;
4228 case RISCV::PseudoFLH:
4229 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
4230 return false;
4231 case RISCV::PseudoFLW:
4232 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
4233 return false;
4234 case RISCV::PseudoFLD:
4235 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
4236 return false;
4237 case RISCV::PseudoFLQ:
4238 emitLoadStoreSymbol(Inst, RISCV::FLQ, IDLoc, Out, /*HasTmpReg=*/true);
4239 return false;
4240 case RISCV::PseudoSB:
4241 case RISCV::PseudoQC_E_SB:
4242 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
4243 return false;
4244 case RISCV::PseudoSH:
4245 case RISCV::PseudoQC_E_SH:
4246 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
4247 return false;
4248 case RISCV::PseudoSW:
4249 case RISCV::PseudoQC_E_SW:
4250 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
4251 return false;
4252 case RISCV::PseudoSD:
4253 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
4254 return false;
4255 case RISCV::PseudoSD_RV32:
4256 emitLoadStoreSymbol(Inst, RISCV::SD_RV32, IDLoc, Out, /*HasTmpReg=*/true);
4257 return false;
4258 case RISCV::PseudoFSH:
4259 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
4260 return false;
4261 case RISCV::PseudoFSW:
4262 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
4263 return false;
4264 case RISCV::PseudoFSD:
4265 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
4266 return false;
4267 case RISCV::PseudoFSQ:
4268 emitLoadStoreSymbol(Inst, RISCV::FSQ, IDLoc, Out, /*HasTmpReg=*/true);
4269 return false;
4270 case RISCV::PseudoAddTPRel:
4271 if (checkPseudoAddTPRel(Inst, Operands))
4272 return true;
4273 break;
4274 case RISCV::PseudoTLSDESCCall:
4275 if (checkPseudoTLSDESCCall(Inst, Operands))
4276 return true;
4277 break;
4278 case RISCV::PseudoSEXT_B:
4279 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
4280 return false;
4281 case RISCV::PseudoSEXT_H:
4282 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
4283 return false;
4284 case RISCV::PseudoZEXT_H:
4285 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
4286 return false;
4287 case RISCV::PseudoZEXT_W:
4288 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
4289 return false;
4290 case RISCV::PseudoVMSGEU_VX:
4291 case RISCV::PseudoVMSGEU_VX_M:
4292 case RISCV::PseudoVMSGEU_VX_M_T:
4293 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
4294 return false;
4295 case RISCV::PseudoVMSGE_VX:
4296 case RISCV::PseudoVMSGE_VX_M:
4297 case RISCV::PseudoVMSGE_VX_M_T:
4298 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
4299 return false;
4300 case RISCV::PseudoVMSGE_VI:
4301 case RISCV::PseudoVMSLT_VI: {
4302 // These instructions are signed and so is immediate so we can subtract one
4303 // and change the opcode.
4304 int64_t Imm = Inst.getOperand(2).getImm();
4305 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
4306 : RISCV::VMSLE_VI;
4307 emitToStreamer(Out, MCInstBuilder(Opc)
4308 .addOperand(Inst.getOperand(0))
4309 .addOperand(Inst.getOperand(1))
4310 .addImm(Imm - 1)
4311 .addOperand(Inst.getOperand(3))
4312 .setLoc(IDLoc));
4313 return false;
4314 }
4315 case RISCV::PseudoVMSGEU_VI:
4316 case RISCV::PseudoVMSLTU_VI: {
4317 int64_t Imm = Inst.getOperand(2).getImm();
4318 // Unsigned comparisons are tricky because the immediate is signed. If the
4319 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
4320 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
4321 // vmsne v0, v1, v1 which is always false.
4322 if (Imm == 0) {
4323 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4324 ? RISCV::VMSEQ_VV
4325 : RISCV::VMSNE_VV;
4326 emitToStreamer(Out, MCInstBuilder(Opc)
4327 .addOperand(Inst.getOperand(0))
4328 .addOperand(Inst.getOperand(1))
4329 .addOperand(Inst.getOperand(1))
4330 .addOperand(Inst.getOperand(3))
4331 .setLoc(IDLoc));
4332 } else {
4333 // Other immediate values can subtract one like signed.
4334 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
4335 ? RISCV::VMSGTU_VI
4336 : RISCV::VMSLEU_VI;
4337 emitToStreamer(Out, MCInstBuilder(Opc)
4338 .addOperand(Inst.getOperand(0))
4339 .addOperand(Inst.getOperand(1))
4340 .addImm(Imm - 1)
4341 .addOperand(Inst.getOperand(3))
4342 .setLoc(IDLoc));
4343 }
4344
4345 return false;
4346 }
4347 case RISCV::PseudoCV_ELW:
4348 emitLoadStoreSymbol(Inst, RISCV::CV_ELW, IDLoc, Out, /*HasTmpReg=*/false);
4349 return false;
4350 }
4351
4352 emitToStreamer(Out, Inst);
4353 return false;
4354}
4355
4356extern "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:862
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
Used to provide key value pairs for feature and CPU bit flags.