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