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