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