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