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