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