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