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