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