Thanks to visit codestin.com
Credit goes to llvm.org

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