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