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