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