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