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