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