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