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