LLVM 18.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"
21#include "llvm/ADT/Statistic.h"
23#include "llvm/MC/MCAssembler.h"
24#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
28#include "llvm/MC/MCInstrInfo.h"
34#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCValue.h"
43
44#include <limits>
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::FeatureRVE); }
88
89 RISCVTargetStreamer &getTargetStreamer() {
90 assert(getParser().getStreamer().getTargetStreamer() &&
91 "do not have a target streamer");
93 return static_cast<RISCVTargetStreamer &>(TS);
94 }
95
97 unsigned Kind) override;
98 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
99
100 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
101 int64_t Lower, int64_t Upper,
102 const Twine &Msg);
103 bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
104 const Twine &Msg);
105
106 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
109 bool MatchingInlineAsm) override;
110
111 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
113 SMLoc &EndLoc) override;
114
116 SMLoc NameLoc, OperandVector &Operands) override;
117
118 ParseStatus parseDirective(AsmToken DirectiveID) override;
119
120 bool parseVTypeToken(StringRef Identifier, VTypeState &State, unsigned &Sew,
121 unsigned &Lmul, bool &Fractional, bool &TailAgnostic,
122 bool &MaskAgnostic);
123 bool generateVTypeError(SMLoc ErrorLoc);
124
125 // Helper to actually emit an instruction to the MCStreamer. Also, when
126 // possible, compression of the instruction is performed.
127 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
128
129 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
130 // synthesize the desired immedate value into the destination register.
131 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
132
133 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
134 // helpers such as emitLoadLocalAddress and emitLoadAddress.
135 void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
136 const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
137 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
138
139 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
140 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
141
142 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
143 void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
144
145 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
146 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
147
148 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
149 // addressing.
150 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
151
152 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
153 // addressing.
154 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
155
156 // Helper to emit pseudo load/store instruction with a symbol.
157 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
158 MCStreamer &Out, bool HasTmpReg);
159
160 // Helper to emit pseudo sign/zero extend instruction.
161 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
162 SMLoc IDLoc, MCStreamer &Out);
163
164 // Helper to emit pseudo vmsge{u}.vx instruction.
165 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
166
167 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
168 // Enforcing this using a restricted register class for the second input
169 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
170 // 'add' is an overloaded mnemonic.
171 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
172
173 // Check instruction constraints.
174 bool validateInstruction(MCInst &Inst, OperandVector &Operands);
175
176 /// Helper for processing MC instructions that have been successfully matched
177 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
178 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
179 /// in this method.
180 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
181 MCStreamer &Out);
182
183// Auto-generated instruction matching functions
184#define GET_ASSEMBLER_HEADER
185#include "RISCVGenAsmMatcher.inc"
186
187 ParseStatus parseCSRSystemRegister(OperandVector &Operands);
190 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
191 ParseStatus parseMemOpBaseReg(OperandVector &Operands);
192 ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
193 ParseStatus parseOperandWithModifier(OperandVector &Operands);
194 ParseStatus parseBareSymbol(OperandVector &Operands);
195 ParseStatus parseCallSymbol(OperandVector &Operands);
196 ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);
197 ParseStatus parseJALOffset(OperandVector &Operands);
198 ParseStatus parseVTypeI(OperandVector &Operands);
199 ParseStatus parseMaskReg(OperandVector &Operands);
200 ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
201 ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
202 ParseStatus parseGPRAsFPR(OperandVector &Operands);
203 ParseStatus parseFRMArg(OperandVector &Operands);
204 ParseStatus parseFenceArg(OperandVector &Operands);
205 ParseStatus parseReglist(OperandVector &Operands);
206 ParseStatus parseRetval(OperandVector &Operands);
207 ParseStatus parseZcmpSpimm(OperandVector &Operands);
208
209 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
210
211 bool parseDirectiveOption();
212 bool parseDirectiveAttribute();
213 bool parseDirectiveInsn(SMLoc L);
214 bool parseDirectiveVariantCC();
215
216 /// Helper to reset target features for a new arch string. It
217 /// also records the new arch string that is expanded by RISCVISAInfo
218 /// and reports error for invalid arch string.
219 bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
220 bool FromOptionDirective);
221
222 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
223 if (!(getSTI().hasFeature(Feature))) {
224 MCSubtargetInfo &STI = copySTI();
226 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
227 }
228 }
229
230 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
231 if (getSTI().hasFeature(Feature)) {
232 MCSubtargetInfo &STI = copySTI();
234 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
235 }
236 }
237
238 void pushFeatureBits() {
239 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
240 "These two stacks must be kept synchronized");
241 FeatureBitStack.push_back(getSTI().getFeatureBits());
242 ParserOptionsStack.push_back(ParserOptions);
243 }
244
245 bool popFeatureBits() {
246 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
247 "These two stacks must be kept synchronized");
248 if (FeatureBitStack.empty())
249 return true;
250
251 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
252 copySTI().setFeatureBits(FeatureBits);
253 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
254
255 ParserOptions = ParserOptionsStack.pop_back_val();
256
257 return false;
258 }
259
260 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
261 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
262 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
263
264public:
265 enum RISCVMatchResultTy {
266 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
267 Match_RequiresEvenGPRs,
268#define GET_OPERAND_DIAGNOSTIC_TYPES
269#include "RISCVGenAsmMatcher.inc"
270#undef GET_OPERAND_DIAGNOSTIC_TYPES
271 };
272
273 static bool classifySymbolRef(const MCExpr *Expr,
275 static bool isSymbolDiff(const MCExpr *Expr);
276
277 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
278 const MCInstrInfo &MII, const MCTargetOptions &Options)
279 : MCTargetAsmParser(Options, STI, MII) {
281
282 Parser.addAliasForDirective(".half", ".2byte");
283 Parser.addAliasForDirective(".hword", ".2byte");
284 Parser.addAliasForDirective(".word", ".4byte");
285 Parser.addAliasForDirective(".dword", ".8byte");
286 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
287
288 auto ABIName = StringRef(Options.ABIName);
289 if (ABIName.endswith("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
290 errs() << "Hard-float 'f' ABI can't be used for a target that "
291 "doesn't support the F instruction set extension (ignoring "
292 "target-abi)\n";
293 } else if (ABIName.endswith("d") &&
294 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
295 errs() << "Hard-float 'd' ABI can't be used for a target that "
296 "doesn't support the D instruction set extension (ignoring "
297 "target-abi)\n";
298 }
299
300 // Use computeTargetABI to check if ABIName is valid. If invalid, output
301 // error message.
303 ABIName);
304
305 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
306 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
307
309 getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
310 }
311};
312
313/// RISCVOperand - Instances of this class represent a parsed machine
314/// instruction
315struct RISCVOperand final : public MCParsedAsmOperand {
316
317 enum class KindTy {
318 Token,
319 Register,
320 Immediate,
321 FPImmediate,
322 SystemRegister,
323 VType,
324 FRM,
325 Fence,
326 Rlist,
327 Spimm,
328 } Kind;
329
330 struct RegOp {
331 MCRegister RegNum;
332 bool IsGPRAsFPR;
333 };
334
335 struct ImmOp {
336 const MCExpr *Val;
337 bool IsRV64;
338 };
339
340 struct FPImmOp {
341 uint64_t Val;
342 };
343
344 struct SysRegOp {
345 const char *Data;
346 unsigned Length;
347 unsigned Encoding;
348 // FIXME: Add the Encoding parsed fields as needed for checks,
349 // e.g.: read/write or user/supervisor/machine privileges.
350 };
351
352 struct VTypeOp {
353 unsigned Val;
354 };
355
356 struct FRMOp {
358 };
359
360 struct FenceOp {
361 unsigned Val;
362 };
363
364 struct RlistOp {
365 unsigned Val;
366 };
367
368 struct SpimmOp {
369 unsigned Val;
370 };
371
372 SMLoc StartLoc, EndLoc;
373 union {
374 StringRef Tok;
375 RegOp Reg;
376 ImmOp Imm;
377 FPImmOp FPImm;
378 struct SysRegOp SysReg;
379 struct VTypeOp VType;
380 struct FRMOp FRM;
381 struct FenceOp Fence;
382 struct RlistOp Rlist;
383 struct SpimmOp Spimm;
384 };
385
386 RISCVOperand(KindTy K) : Kind(K) {}
387
388public:
389 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
390 Kind = o.Kind;
391 StartLoc = o.StartLoc;
392 EndLoc = o.EndLoc;
393 switch (Kind) {
394 case KindTy::Register:
395 Reg = o.Reg;
396 break;
397 case KindTy::Immediate:
398 Imm = o.Imm;
399 break;
400 case KindTy::FPImmediate:
401 FPImm = o.FPImm;
402 break;
403 case KindTy::Token:
404 Tok = o.Tok;
405 break;
406 case KindTy::SystemRegister:
407 SysReg = o.SysReg;
408 break;
409 case KindTy::VType:
410 VType = o.VType;
411 break;
412 case KindTy::FRM:
413 FRM = o.FRM;
414 break;
415 case KindTy::Fence:
416 Fence = o.Fence;
417 break;
418 case KindTy::Rlist:
419 Rlist = o.Rlist;
420 break;
421 case KindTy::Spimm:
422 Spimm = o.Spimm;
423 break;
424 }
425 }
426
427 bool isToken() const override { return Kind == KindTy::Token; }
428 bool isReg() const override { return Kind == KindTy::Register; }
429 bool isV0Reg() const {
430 return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
431 }
432 bool isAnyReg() const {
433 return Kind == KindTy::Register &&
434 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) ||
435 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||
436 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));
437 }
438 bool isAnyRegC() const {
439 return Kind == KindTy::Register &&
440 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
441 Reg.RegNum) ||
442 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
443 Reg.RegNum));
444 }
445 bool isImm() const override { return Kind == KindTy::Immediate; }
446 bool isMem() const override { return false; }
447 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
448 bool isRlist() const { return Kind == KindTy::Rlist; }
449 bool isSpimm() const { return Kind == KindTy::Spimm; }
450
451 bool isGPR() const {
452 return Kind == KindTy::Register &&
453 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
454 }
455
456 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
457
458 bool isGPRF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
459
460 bool isGPRPF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
461
462 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
464 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
465 VK = RE->getKind();
466 return RE->evaluateAsConstant(Imm);
467 }
468
469 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
471 Imm = CE->getValue();
472 return true;
473 }
474
475 return false;
476 }
477
478 // True if operand is a symbol with no modifiers, or a constant with no
479 // modifiers and isShiftedInt<N-1, 1>(Op).
480 template <int N> bool isBareSimmNLsb0() const {
481 int64_t Imm;
483 if (!isImm())
484 return false;
485 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
486 bool IsValid;
487 if (!IsConstantImm)
488 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
489 else
490 IsValid = isShiftedInt<N - 1, 1>(Imm);
491 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
492 }
493
494 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
495
496 bool isBareSymbol() const {
497 int64_t Imm;
499 // Must be of 'immediate' type but not a constant.
500 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
501 return false;
502 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
504 }
505
506 bool isCallSymbol() const {
507 int64_t Imm;
509 // Must be of 'immediate' type but not a constant.
510 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
511 return false;
512 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
515 }
516
517 bool isPseudoJumpSymbol() const {
518 int64_t Imm;
520 // Must be of 'immediate' type but not a constant.
521 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
522 return false;
523 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
525 }
526
527 bool isTPRelAddSymbol() const {
528 int64_t Imm;
530 // Must be of 'immediate' type but not a constant.
531 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
532 return false;
533 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
535 }
536
537 bool isCSRSystemRegister() const { return isSystemRegister(); }
538
539 bool isVTypeImm(unsigned N) const {
540 int64_t Imm;
542 if (!isImm())
543 return false;
544 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
545 return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
546 }
547
548 // If the last operand of the vsetvli/vsetvli instruction is a constant
549 // expression, KindTy is Immediate.
550 bool isVTypeI10() const {
551 if (Kind == KindTy::Immediate)
552 return isVTypeImm(10);
553 return Kind == KindTy::VType;
554 }
555 bool isVTypeI11() const {
556 if (Kind == KindTy::Immediate)
557 return isVTypeImm(11);
558 return Kind == KindTy::VType;
559 }
560
561 /// Return true if the operand is a valid for the fence instruction e.g.
562 /// ('iorw').
563 bool isFenceArg() const { return Kind == KindTy::Fence; }
564
565 /// Return true if the operand is a valid floating point rounding mode.
566 bool isFRMArg() const { return Kind == KindTy::FRM; }
567 bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }
568 bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
569
570 /// Return true if the operand is a valid fli.s floating-point immediate.
571 bool isLoadFPImm() const {
572 if (isImm())
573 return isUImm5();
574 if (Kind != KindTy::FPImmediate)
575 return false;
577 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
578 // Don't allow decimal version of the minimum value. It is a different value
579 // for each supported data type.
580 return Idx >= 0 && Idx != 1;
581 }
582
583 bool isImmXLenLI() const {
584 int64_t Imm;
586 if (!isImm())
587 return false;
588 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
590 return true;
591 // Given only Imm, ensuring that the actually specified constant is either
592 // a signed or unsigned 64-bit number is unfortunately impossible.
593 if (IsConstantImm) {
594 return VK == RISCVMCExpr::VK_RISCV_None &&
595 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
596 }
597
598 return RISCVAsmParser::isSymbolDiff(getImm());
599 }
600
601 bool isImmXLenLI_Restricted() const {
602 int64_t Imm;
604 if (!isImm())
605 return false;
606 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
607 // 'la imm' supports constant immediates only.
608 return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
609 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
610 }
611
612 bool isUImmLog2XLen() const {
613 int64_t Imm;
615 if (!isImm())
616 return false;
617 if (!evaluateConstantImm(getImm(), Imm, VK) ||
619 return false;
620 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
621 }
622
623 bool isUImmLog2XLenNonZero() const {
624 int64_t Imm;
626 if (!isImm())
627 return false;
628 if (!evaluateConstantImm(getImm(), Imm, VK) ||
630 return false;
631 if (Imm == 0)
632 return false;
633 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
634 }
635
636 bool isUImmLog2XLenHalf() const {
637 int64_t Imm;
639 if (!isImm())
640 return false;
641 if (!evaluateConstantImm(getImm(), Imm, VK) ||
643 return false;
644 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
645 }
646
647 template <unsigned N> bool IsUImm() const {
648 int64_t Imm;
650 if (!isImm())
651 return false;
652 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
653 return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
654 }
655
656 bool isUImm1() const { return IsUImm<1>(); }
657 bool isUImm2() const { return IsUImm<2>(); }
658 bool isUImm3() const { return IsUImm<3>(); }
659 bool isUImm4() const { return IsUImm<4>(); }
660 bool isUImm5() const { return IsUImm<5>(); }
661 bool isUImm6() const { return IsUImm<6>(); }
662 bool isUImm7() const { return IsUImm<7>(); }
663 bool isUImm8() const { return IsUImm<8>(); }
664 bool isUImm20() const { return IsUImm<20>(); }
665
666 bool isUImm8GE32() const {
667 int64_t Imm;
669 if (!isImm())
670 return false;
671 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
672 return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&
674 }
675
676 bool isRnumArg() const {
677 int64_t Imm;
679 if (!isImm())
680 return false;
681 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
682 return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
684 }
685
686 bool isRnumArg_0_7() const {
687 int64_t Imm;
689 if (!isImm())
690 return false;
691 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
692 return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) &&
694 }
695
696 bool isRnumArg_1_10() const {
697 int64_t Imm;
699 if (!isImm())
700 return false;
701 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
702 return IsConstantImm && Imm >= INT64_C(1) && Imm <= INT64_C(10) &&
704 }
705
706 bool isRnumArg_2_14() const {
707 int64_t Imm;
709 if (!isImm())
710 return false;
711 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
712 return IsConstantImm && Imm >= INT64_C(2) && Imm <= INT64_C(14) &&
714 }
715
716 bool isSImm5() const {
717 if (!isImm())
718 return false;
720 int64_t Imm;
721 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
722 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
724 }
725
726 bool isSImm6() const {
727 if (!isImm())
728 return false;
730 int64_t Imm;
731 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
732 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
734 }
735
736 bool isSImm6NonZero() const {
737 if (!isImm())
738 return false;
740 int64_t Imm;
741 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
742 return IsConstantImm && Imm != 0 &&
743 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
745 }
746
747 bool isCLUIImm() const {
748 if (!isImm())
749 return false;
750 int64_t Imm;
752 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
753 return IsConstantImm && (Imm != 0) &&
754 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
756 }
757
758 bool isUImm2Lsb0() const {
759 if (!isImm())
760 return false;
761 int64_t Imm;
763 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
764 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
766 }
767
768 bool isUImm7Lsb00() const {
769 if (!isImm())
770 return false;
771 int64_t Imm;
773 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
774 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
776 }
777
778 bool isUImm8Lsb00() const {
779 if (!isImm())
780 return false;
781 int64_t Imm;
783 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
784 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
786 }
787
788 bool isUImm8Lsb000() const {
789 if (!isImm())
790 return false;
791 int64_t Imm;
793 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
794 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
796 }
797
798 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
799
800 bool isUImm9Lsb000() const {
801 if (!isImm())
802 return false;
803 int64_t Imm;
805 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
806 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
808 }
809
810 bool isUImm10Lsb00NonZero() const {
811 if (!isImm())
812 return false;
813 int64_t Imm;
815 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
816 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
818 }
819
820 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
821 // This allows writing 'addi a0, a0, 0xffffffff'.
822 static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
823 if (IsRV64Imm || !isUInt<32>(Imm))
824 return Imm;
825 return SignExtend64<32>(Imm);
826 }
827
828 bool isSImm12() const {
830 int64_t Imm;
831 bool IsValid;
832 if (!isImm())
833 return false;
834 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
835 if (!IsConstantImm)
836 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
837 else
838 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
839 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
843 }
844
845 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
846
847 bool isSImm12Lsb00000() const {
848 if (!isImm())
849 return false;
851 int64_t Imm;
852 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
853 return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
855 }
856
857 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
858
859 bool isSImm10Lsb0000NonZero() const {
860 if (!isImm())
861 return false;
862 int64_t Imm;
864 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
865 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
867 }
868
869 bool isUImm20LUI() const {
871 int64_t Imm;
872 bool IsValid;
873 if (!isImm())
874 return false;
875 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
876 if (!IsConstantImm) {
877 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
878 return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
880 } else {
881 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
884 }
885 }
886
887 bool isUImm20AUIPC() const {
889 int64_t Imm;
890 bool IsValid;
891 if (!isImm())
892 return false;
893 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
894 if (!IsConstantImm) {
895 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
896 return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
900 } else {
901 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
906 }
907 }
908
909 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
910
911 bool isImmZero() const {
912 if (!isImm())
913 return false;
914 int64_t Imm;
916 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
917 return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
918 }
919
920 bool isSImm5Plus1() const {
921 if (!isImm())
922 return false;
924 int64_t Imm;
925 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
926 return IsConstantImm &&
927 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
929 }
930
931 /// getStartLoc - Gets location of the first token of this operand
932 SMLoc getStartLoc() const override { return StartLoc; }
933 /// getEndLoc - Gets location of the last token of this operand
934 SMLoc getEndLoc() const override { return EndLoc; }
935 /// True if this operand is for an RV64 instruction
936 bool isRV64Imm() const {
937 assert(Kind == KindTy::Immediate && "Invalid type access!");
938 return Imm.IsRV64;
939 }
940
941 unsigned getReg() const override {
942 assert(Kind == KindTy::Register && "Invalid type access!");
943 return Reg.RegNum.id();
944 }
945
946 StringRef getSysReg() const {
947 assert(Kind == KindTy::SystemRegister && "Invalid type access!");
948 return StringRef(SysReg.Data, SysReg.Length);
949 }
950
951 const MCExpr *getImm() const {
952 assert(Kind == KindTy::Immediate && "Invalid type access!");
953 return Imm.Val;
954 }
955
956 uint64_t getFPConst() const {
957 assert(Kind == KindTy::FPImmediate && "Invalid type access!");
958 return FPImm.Val;
959 }
960
961 StringRef getToken() const {
962 assert(Kind == KindTy::Token && "Invalid type access!");
963 return Tok;
964 }
965
966 unsigned getVType() const {
967 assert(Kind == KindTy::VType && "Invalid type access!");
968 return VType.Val;
969 }
970
971 RISCVFPRndMode::RoundingMode getFRM() const {
972 assert(Kind == KindTy::FRM && "Invalid type access!");
973 return FRM.FRM;
974 }
975
976 unsigned getFence() const {
977 assert(Kind == KindTy::Fence && "Invalid type access!");
978 return Fence.Val;
979 }
980
981 void print(raw_ostream &OS) const override {
982 auto RegName = [](MCRegister Reg) {
983 if (Reg)
985 else
986 return "noreg";
987 };
988
989 switch (Kind) {
990 case KindTy::Immediate:
991 OS << *getImm();
992 break;
993 case KindTy::FPImmediate:
994 break;
995 case KindTy::Register:
996 OS << "<register " << RegName(getReg()) << ">";
997 break;
998 case KindTy::Token:
999 OS << "'" << getToken() << "'";
1000 break;
1001 case KindTy::SystemRegister:
1002 OS << "<sysreg: " << getSysReg() << '>';
1003 break;
1004 case KindTy::VType:
1005 OS << "<vtype: ";
1006 RISCVVType::printVType(getVType(), OS);
1007 OS << '>';
1008 break;
1009 case KindTy::FRM:
1010 OS << "<frm: ";
1011 roundingModeToString(getFRM());
1012 OS << '>';
1013 break;
1014 case KindTy::Fence:
1015 OS << "<fence: ";
1016 OS << getFence();
1017 OS << '>';
1018 break;
1019 case KindTy::Rlist:
1020 OS << "<rlist: ";
1021 RISCVZC::printRlist(Rlist.Val, OS);
1022 OS << '>';
1023 break;
1024 case KindTy::Spimm:
1025 OS << "<Spimm: ";
1026 RISCVZC::printSpimm(Spimm.Val, OS);
1027 OS << '>';
1028 break;
1029 }
1030 }
1031
1032 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
1033 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1034 Op->Tok = Str;
1035 Op->StartLoc = S;
1036 Op->EndLoc = S;
1037 return Op;
1038 }
1039
1040 static std::unique_ptr<RISCVOperand>
1041 createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
1042 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1043 Op->Reg.RegNum = RegNo;
1044 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1045 Op->StartLoc = S;
1046 Op->EndLoc = E;
1047 return Op;
1048 }
1049
1050 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
1051 SMLoc E, bool IsRV64) {
1052 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1053 Op->Imm.Val = Val;
1054 Op->Imm.IsRV64 = IsRV64;
1055 Op->StartLoc = S;
1056 Op->EndLoc = E;
1057 return Op;
1058 }
1059
1060 static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
1061 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1062 Op->FPImm.Val = Val;
1063 Op->StartLoc = S;
1064 Op->EndLoc = S;
1065 return Op;
1066 }
1067
1068 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
1069 unsigned Encoding) {
1070 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1071 Op->SysReg.Data = Str.data();
1072 Op->SysReg.Length = Str.size();
1073 Op->SysReg.Encoding = Encoding;
1074 Op->StartLoc = S;
1075 Op->EndLoc = S;
1076 return Op;
1077 }
1078
1079 static std::unique_ptr<RISCVOperand>
1080 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
1081 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1082 Op->FRM.FRM = FRM;
1083 Op->StartLoc = S;
1084 Op->EndLoc = S;
1085 return Op;
1086 }
1087
1088 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
1089 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1090 Op->Fence.Val = Val;
1091 Op->StartLoc = S;
1092 Op->EndLoc = S;
1093 return Op;
1094 }
1095
1096 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
1097 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1098 Op->VType.Val = VTypeI;
1099 Op->StartLoc = S;
1100 Op->EndLoc = S;
1101 return Op;
1102 }
1103
1104 static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,
1105 SMLoc S) {
1106 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1107 Op->Rlist.Val = RlistEncode;
1108 Op->StartLoc = S;
1109 return Op;
1110 }
1111
1112 static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {
1113 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1114 Op->Spimm.Val = Spimm;
1115 Op->StartLoc = S;
1116 return Op;
1117 }
1118
1119 static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
1120 assert(Expr && "Expr shouldn't be null!");
1121 int64_t Imm = 0;
1123 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1124
1125 if (IsConstant)
1126 Inst.addOperand(
1127 MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
1128 else
1130 }
1131
1132 // Used by the TableGen Code
1133 void addRegOperands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
1136 }
1137
1138 void addImmOperands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!");
1140 addExpr(Inst, getImm(), isRV64Imm());
1141 }
1142
1143 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
1145 if (isImm()) {
1146 addExpr(Inst, getImm(), isRV64Imm());
1147 return;
1148 }
1149
1151 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1153 }
1154
1155 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
1157 Inst.addOperand(MCOperand::createImm(Fence.Val));
1158 }
1159
1160 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
1163 }
1164
1165 // Support non-canonical syntax:
1166 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1167 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1168 void addVTypeIOperands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 int64_t Imm = 0;
1171 if (Kind == KindTy::Immediate) {
1173 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1174 (void)IsConstantImm;
1175 assert(IsConstantImm && "Invalid VTypeI Operand!");
1176 } else {
1177 Imm = getVType();
1178 }
1180 }
1181
1182 void addRlistOperands(MCInst &Inst, unsigned N) const {
1183 assert(N == 1 && "Invalid number of operands!");
1184 Inst.addOperand(MCOperand::createImm(Rlist.Val));
1185 }
1186
1187 void addSpimmOperands(MCInst &Inst, unsigned N) const {
1188 assert(N == 1 && "Invalid number of operands!");
1189 Inst.addOperand(MCOperand::createImm(Spimm.Val));
1190 }
1191
1192 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
1193 assert(N == 1 && "Invalid number of operands!");
1194 Inst.addOperand(MCOperand::createImm(getFRM()));
1195 }
1196};
1197} // end anonymous namespace.
1198
1199#define GET_REGISTER_MATCHER
1200#define GET_SUBTARGET_FEATURE_NAME
1201#define GET_MATCHER_IMPLEMENTATION
1202#define GET_MNEMONIC_SPELL_CHECKER
1203#include "RISCVGenAsmMatcher.inc"
1204
1206 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1207 return Reg - RISCV::F0_D + RISCV::F0_H;
1208}
1209
1211 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1212 return Reg - RISCV::F0_D + RISCV::F0_F;
1213}
1214
1216 unsigned Kind) {
1217 unsigned RegClassID;
1218 if (Kind == MCK_VRM2)
1219 RegClassID = RISCV::VRM2RegClassID;
1220 else if (Kind == MCK_VRM4)
1221 RegClassID = RISCV::VRM4RegClassID;
1222 else if (Kind == MCK_VRM8)
1223 RegClassID = RISCV::VRM8RegClassID;
1224 else
1225 return 0;
1226 return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
1227 &RISCVMCRegisterClasses[RegClassID]);
1228}
1229
1230unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1231 unsigned Kind) {
1232 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1233 if (!Op.isReg())
1234 return Match_InvalidOperand;
1235
1236 MCRegister Reg = Op.getReg();
1237 bool IsRegFPR64 =
1238 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1239 bool IsRegFPR64C =
1240 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1241 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1242
1243 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1244 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1245 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1246 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1247 Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
1248 return Match_Success;
1249 }
1250 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1251 // register from FPR64 to FPR16 if necessary.
1252 if (IsRegFPR64 && Kind == MCK_FPR16) {
1253 Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1254 return Match_Success;
1255 }
1256 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1257 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1258 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1259 Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1260 if (Op.Reg.RegNum == 0)
1261 return Match_InvalidOperand;
1262 return Match_Success;
1263 }
1264 return Match_InvalidOperand;
1265}
1266
1267unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1268 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
1269
1270 for (unsigned I = 0; I < MCID.NumOperands; ++I) {
1271 if (MCID.operands()[I].RegClass == RISCV::GPRPF64RegClassID) {
1272 const auto &Op = Inst.getOperand(I);
1273 assert(Op.isReg());
1274
1275 MCRegister Reg = Op.getReg();
1276 if (((Reg.id() - RISCV::X0) & 1) != 0)
1277 return Match_RequiresEvenGPRs;
1278 }
1279 }
1280
1281 return Match_Success;
1282}
1283
1284bool RISCVAsmParser::generateImmOutOfRangeError(
1285 SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
1286 const Twine &Msg = "immediate must be an integer in the range") {
1287 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1288}
1289
1290bool RISCVAsmParser::generateImmOutOfRangeError(
1291 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1292 const Twine &Msg = "immediate must be an integer in the range") {
1293 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1294 return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);
1295}
1296
1297bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1299 MCStreamer &Out,
1301 bool MatchingInlineAsm) {
1302 MCInst Inst;
1303 FeatureBitset MissingFeatures;
1304
1305 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1306 MatchingInlineAsm);
1307 switch (Result) {
1308 default:
1309 break;
1310 case Match_Success:
1311 if (validateInstruction(Inst, Operands))
1312 return true;
1313 return processInstruction(Inst, IDLoc, Operands, Out);
1314 case Match_MissingFeature: {
1315 assert(MissingFeatures.any() && "Unknown missing features!");
1316 bool FirstFeature = true;
1317 std::string Msg = "instruction requires the following:";
1318 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1319 if (MissingFeatures[i]) {
1320 Msg += FirstFeature ? " " : ", ";
1322 FirstFeature = false;
1323 }
1324 }
1325 return Error(IDLoc, Msg);
1326 }
1327 case Match_MnemonicFail: {
1328 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1329 std::string Suggestion = RISCVMnemonicSpellCheck(
1330 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1331 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1332 }
1333 case Match_InvalidOperand: {
1334 SMLoc ErrorLoc = IDLoc;
1335 if (ErrorInfo != ~0ULL) {
1336 if (ErrorInfo >= Operands.size())
1337 return Error(ErrorLoc, "too few operands for instruction");
1338
1339 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1340 if (ErrorLoc == SMLoc())
1341 ErrorLoc = IDLoc;
1342 }
1343 return Error(ErrorLoc, "invalid operand for instruction");
1344 }
1345 }
1346
1347 // Handle the case when the error message is of specific type
1348 // other than the generic Match_InvalidOperand, and the
1349 // corresponding operand is missing.
1350 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1351 SMLoc ErrorLoc = IDLoc;
1352 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1353 return Error(ErrorLoc, "too few operands for instruction");
1354 }
1355
1356 switch (Result) {
1357 default:
1358 break;
1359 case Match_RequiresEvenGPRs:
1360 return Error(IDLoc,
1361 "double precision floating point operands must use even "
1362 "numbered X register");
1363 case Match_InvalidImmXLenLI:
1364 if (isRV64()) {
1365 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1366 return Error(ErrorLoc, "operand must be a constant 64-bit integer");
1367 }
1368 return generateImmOutOfRangeError(Operands, ErrorInfo,
1369 std::numeric_limits<int32_t>::min(),
1370 std::numeric_limits<uint32_t>::max());
1371 case Match_InvalidImmXLenLI_Restricted:
1372 if (isRV64()) {
1373 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1374 return Error(ErrorLoc, "operand either must be a constant 64-bit integer "
1375 "or a bare symbol name");
1376 }
1377 return generateImmOutOfRangeError(
1378 Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),
1379 std::numeric_limits<uint32_t>::max(),
1380 "operand either must be a bare symbol name or an immediate integer in "
1381 "the range");
1382 case Match_InvalidImmZero: {
1383 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1384 return Error(ErrorLoc, "immediate must be zero");
1385 }
1386 case Match_InvalidUImmLog2XLen:
1387 if (isRV64())
1388 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1389 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1390 case Match_InvalidUImmLog2XLenNonZero:
1391 if (isRV64())
1392 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
1393 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
1394 case Match_InvalidUImmLog2XLenHalf:
1395 if (isRV64())
1396 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1397 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1398 case Match_InvalidUImm1:
1399 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
1400 case Match_InvalidUImm2:
1401 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1402 case Match_InvalidUImm2Lsb0:
1403 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
1404 "immediate must be one of");
1405 case Match_InvalidUImm3:
1406 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
1407 case Match_InvalidUImm4:
1408 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1409 case Match_InvalidUImm5:
1410 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1411 case Match_InvalidUImm6:
1412 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1413 case Match_InvalidUImm7:
1414 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
1415 case Match_InvalidUImm8:
1416 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
1417 case Match_InvalidUImm8GE32:
1418 return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);
1419 case Match_InvalidSImm5:
1420 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1421 (1 << 4) - 1);
1422 case Match_InvalidSImm6:
1423 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1424 (1 << 5) - 1);
1425 case Match_InvalidSImm6NonZero:
1426 return generateImmOutOfRangeError(
1427 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1428 "immediate must be non-zero in the range");
1429 case Match_InvalidCLUIImm:
1430 return generateImmOutOfRangeError(
1431 Operands, ErrorInfo, 1, (1 << 5) - 1,
1432 "immediate must be in [0xfffe0, 0xfffff] or");
1433 case Match_InvalidUImm7Lsb00:
1434 return generateImmOutOfRangeError(
1435 Operands, ErrorInfo, 0, (1 << 7) - 4,
1436 "immediate must be a multiple of 4 bytes in the range");
1437 case Match_InvalidUImm8Lsb00:
1438 return generateImmOutOfRangeError(
1439 Operands, ErrorInfo, 0, (1 << 8) - 4,
1440 "immediate must be a multiple of 4 bytes in the range");
1441 case Match_InvalidUImm8Lsb000:
1442 return generateImmOutOfRangeError(
1443 Operands, ErrorInfo, 0, (1 << 8) - 8,
1444 "immediate must be a multiple of 8 bytes in the range");
1445 case Match_InvalidSImm9Lsb0:
1446 return generateImmOutOfRangeError(
1447 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1448 "immediate must be a multiple of 2 bytes in the range");
1449 case Match_InvalidUImm9Lsb000:
1450 return generateImmOutOfRangeError(
1451 Operands, ErrorInfo, 0, (1 << 9) - 8,
1452 "immediate must be a multiple of 8 bytes in the range");
1453 case Match_InvalidUImm10Lsb00NonZero:
1454 return generateImmOutOfRangeError(
1455 Operands, ErrorInfo, 4, (1 << 10) - 4,
1456 "immediate must be a multiple of 4 bytes in the range");
1457 case Match_InvalidSImm10Lsb0000NonZero:
1458 return generateImmOutOfRangeError(
1459 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1460 "immediate must be a multiple of 16 bytes and non-zero in the range");
1461 case Match_InvalidSImm12:
1462 return generateImmOutOfRangeError(
1463 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1464 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1465 "integer in the range");
1466 case Match_InvalidSImm12Lsb0:
1467 return generateImmOutOfRangeError(
1468 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1469 "immediate must be a multiple of 2 bytes in the range");
1470 case Match_InvalidSImm12Lsb00000:
1471 return generateImmOutOfRangeError(
1472 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
1473 "immediate must be a multiple of 32 bytes in the range");
1474 case Match_InvalidSImm13Lsb0:
1475 return generateImmOutOfRangeError(
1476 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1477 "immediate must be a multiple of 2 bytes in the range");
1478 case Match_InvalidUImm20LUI:
1479 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1480 "operand must be a symbol with "
1481 "%hi/%tprel_hi modifier or an integer in "
1482 "the range");
1483 case Match_InvalidUImm20:
1484 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
1485 case Match_InvalidUImm20AUIPC:
1486 return generateImmOutOfRangeError(
1487 Operands, ErrorInfo, 0, (1 << 20) - 1,
1488 "operand must be a symbol with a "
1489 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1490 "an integer in the range");
1491 case Match_InvalidSImm21Lsb0JAL:
1492 return generateImmOutOfRangeError(
1493 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1494 "immediate must be a multiple of 2 bytes in the range");
1495 case Match_InvalidCSRSystemRegister: {
1496 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1497 "operand must be a valid system register "
1498 "name or an integer in the range");
1499 }
1500 case Match_InvalidLoadFPImm: {
1501 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1502 return Error(ErrorLoc, "operand must be a valid floating-point constant");
1503 }
1504 case Match_InvalidBareSymbol: {
1505 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1506 return Error(ErrorLoc, "operand must be a bare symbol name");
1507 }
1508 case Match_InvalidPseudoJumpSymbol: {
1509 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1510 return Error(ErrorLoc, "operand must be a valid jump target");
1511 }
1512 case Match_InvalidCallSymbol: {
1513 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1514 return Error(ErrorLoc, "operand must be a bare symbol name");
1515 }
1516 case Match_InvalidTPRelAddSymbol: {
1517 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1518 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1519 }
1520 case Match_InvalidRTZArg: {
1521 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1522 return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
1523 }
1524 case Match_InvalidVTypeI: {
1525 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1526 return generateVTypeError(ErrorLoc);
1527 }
1528 case Match_InvalidVMaskRegister: {
1529 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1530 return Error(ErrorLoc, "operand must be v0.t");
1531 }
1532 case Match_InvalidSImm5Plus1: {
1533 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1534 (1 << 4),
1535 "immediate must be in the range");
1536 }
1537 case Match_InvalidRlist: {
1538 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1539 return Error(
1540 ErrorLoc,
1541 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1542 }
1543 case Match_InvalidSpimm: {
1544 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1545 return Error(
1546 ErrorLoc,
1547 "stack adjustment is invalid for this instruction and register list; "
1548 "refer to Zc spec for a detailed range of stack adjustment");
1549 }
1550 case Match_InvalidRnumArg: {
1551 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1552 }
1553 }
1554
1555 llvm_unreachable("Unknown match type detected!");
1556}
1557
1558// Attempts to match Name as a register (either using the default name or
1559// alternative ABI names), setting RegNo to the matching register. Upon
1560// failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
1561// will be rejected.
1564 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1565 // match always matches the 64-bit variant, and not the 16/32-bit one.
1566 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1567 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1568 // The default FPR register class is based on the tablegen enum ordering.
1569 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1570 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1571 if (!Reg)
1573 if (IsRVE && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1574 Reg = RISCV::NoRegister;
1575 return Reg;
1576}
1577
1578bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1579 SMLoc &EndLoc) {
1580 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1581 return Error(StartLoc, "invalid register name");
1582 return false;
1583}
1584
1585ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1586 SMLoc &EndLoc) {
1587 const AsmToken &Tok = getParser().getTok();
1588 StartLoc = Tok.getLoc();
1589 EndLoc = Tok.getEndLoc();
1590 StringRef Name = getLexer().getTok().getIdentifier();
1591
1592 Reg = matchRegisterNameHelper(isRVE(), Name);
1593 if (!Reg)
1594 return ParseStatus::NoMatch;
1595
1596 getParser().Lex(); // Eat identifier token.
1597 return ParseStatus::Success;
1598}
1599
1600ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1601 bool AllowParens) {
1602 SMLoc FirstS = getLoc();
1603 bool HadParens = false;
1604 AsmToken LParen;
1605
1606 // If this is an LParen and a parenthesised register name is allowed, parse it
1607 // atomically.
1608 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1609 AsmToken Buf[2];
1610 size_t ReadCount = getLexer().peekTokens(Buf);
1611 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1612 HadParens = true;
1613 LParen = getParser().getTok();
1614 getParser().Lex(); // Eat '('
1615 }
1616 }
1617
1618 switch (getLexer().getKind()) {
1619 default:
1620 if (HadParens)
1621 getLexer().UnLex(LParen);
1622 return ParseStatus::NoMatch;
1624 StringRef Name = getLexer().getTok().getIdentifier();
1625 MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
1626
1627 if (!RegNo) {
1628 if (HadParens)
1629 getLexer().UnLex(LParen);
1630 return ParseStatus::NoMatch;
1631 }
1632 if (HadParens)
1633 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1634 SMLoc S = getLoc();
1636 getLexer().Lex();
1637 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
1638 }
1639
1640 if (HadParens) {
1641 getParser().Lex(); // Eat ')'
1642 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1643 }
1644
1645 return ParseStatus::Success;
1646}
1647
1648ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1649 SMLoc S = getLoc();
1650 SMLoc E;
1651 const MCExpr *Res;
1652
1653 switch (getLexer().getKind()) {
1654 default:
1655 return ParseStatus::NoMatch;
1656 case AsmToken::LParen:
1657 case AsmToken::Minus:
1658 case AsmToken::Plus:
1659 case AsmToken::Exclaim:
1660 case AsmToken::Tilde:
1661 case AsmToken::Integer:
1662 case AsmToken::String: {
1663 if (getParser().parseExpression(Res, E))
1664 return ParseStatus::Failure;
1665
1666 auto *CE = dyn_cast<MCConstantExpr>(Res);
1667 if (CE) {
1668 int64_t Imm = CE->getValue();
1669 if (isUInt<7>(Imm)) {
1670 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1671 return ParseStatus::Success;
1672 }
1673 }
1674
1675 break;
1676 }
1677 case AsmToken::Identifier: {
1679 if (getParser().parseIdentifier(Identifier))
1680 return ParseStatus::Failure;
1681
1682 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1683 if (Opcode) {
1684 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1685 "Unexpected opcode");
1686 Res = MCConstantExpr::create(Opcode->Value, getContext());
1688 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1689 return ParseStatus::Success;
1690 }
1691
1692 break;
1693 }
1694 case AsmToken::Percent:
1695 break;
1696 }
1697
1698 return generateImmOutOfRangeError(
1699 S, 0, 127,
1700 "opcode must be a valid opcode name or an immediate in the range");
1701}
1702
1703ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
1704 SMLoc S = getLoc();
1705 SMLoc E;
1706 const MCExpr *Res;
1707
1708 switch (getLexer().getKind()) {
1709 default:
1710 return ParseStatus::NoMatch;
1711 case AsmToken::LParen:
1712 case AsmToken::Minus:
1713 case AsmToken::Plus:
1714 case AsmToken::Exclaim:
1715 case AsmToken::Tilde:
1716 case AsmToken::Integer:
1717 case AsmToken::String: {
1718 if (getParser().parseExpression(Res, E))
1719 return ParseStatus::Failure;
1720
1721 auto *CE = dyn_cast<MCConstantExpr>(Res);
1722 if (CE) {
1723 int64_t Imm = CE->getValue();
1724 if (Imm >= 0 && Imm <= 2) {
1725 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1726 return ParseStatus::Success;
1727 }
1728 }
1729
1730 break;
1731 }
1732 case AsmToken::Identifier: {
1734 if (getParser().parseIdentifier(Identifier))
1735 return ParseStatus::Failure;
1736
1737 unsigned Opcode;
1738 if (Identifier == "C0")
1739 Opcode = 0;
1740 else if (Identifier == "C1")
1741 Opcode = 1;
1742 else if (Identifier == "C2")
1743 Opcode = 2;
1744 else
1745 break;
1746
1747 Res = MCConstantExpr::create(Opcode, getContext());
1749 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1750 return ParseStatus::Success;
1751 }
1752 case AsmToken::Percent: {
1753 // Discard operand with modifier.
1754 break;
1755 }
1756 }
1757
1758 return generateImmOutOfRangeError(
1759 S, 0, 2,
1760 "opcode must be a valid opcode name or an immediate in the range");
1761}
1762
1763ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1764 SMLoc S = getLoc();
1765 const MCExpr *Res;
1766
1767 switch (getLexer().getKind()) {
1768 default:
1769 return ParseStatus::NoMatch;
1770 case AsmToken::LParen:
1771 case AsmToken::Minus:
1772 case AsmToken::Plus:
1773 case AsmToken::Exclaim:
1774 case AsmToken::Tilde:
1775 case AsmToken::Integer:
1776 case AsmToken::String: {
1777 if (getParser().parseExpression(Res))
1778 return ParseStatus::Failure;
1779
1780 auto *CE = dyn_cast<MCConstantExpr>(Res);
1781 if (CE) {
1782 int64_t Imm = CE->getValue();
1783 if (isUInt<12>(Imm)) {
1784 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1785 // Accept an immediate representing a named or un-named Sys Reg
1786 // if the range is valid, regardless of the required features.
1787 Operands.push_back(
1788 RISCVOperand::createSysReg(SysReg ? SysReg->Name : "", S, Imm));
1789 return ParseStatus::Success;
1790 }
1791 }
1792
1793 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1794 }
1795 case AsmToken::Identifier: {
1797 if (getParser().parseIdentifier(Identifier))
1798 return ParseStatus::Failure;
1799
1800 // Check for CSR names conflicts.
1801 // Custom CSR names might conflict with CSR names in privileged spec.
1802 // E.g. - SiFive mnscratch(0x350) and privileged spec mnscratch(0x740).
1803 auto CheckCSRNameConflict = [&]() {
1804 if (!(RISCVSysReg::lookupSysRegByName(Identifier))) {
1805 Error(S, "system register use requires an option to be enabled");
1806 return true;
1807 }
1808 return false;
1809 };
1810
1811 // First check for vendor specific CSRs.
1812 auto SiFiveReg = RISCVSysReg::lookupSiFiveRegByName(Identifier);
1813 if (SiFiveReg) {
1814 if (SiFiveReg->haveVendorRequiredFeatures(getSTI().getFeatureBits())) {
1815 Operands.push_back(
1816 RISCVOperand::createSysReg(Identifier, S, SiFiveReg->Encoding));
1817 return ParseStatus::Success;
1818 }
1819 if (CheckCSRNameConflict())
1820 return ParseStatus::Failure;
1821 }
1822
1823 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1824 if (!SysReg)
1825 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1826 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1827 SysReg->Name + "'");
1828
1829 // Check for CSR encoding conflicts.
1830 // Custom CSR encoding might conflict with CSR encoding in privileged spec.
1831 // E.g. - SiFive mnscratch(0x350) and privileged spec miselect(0x350).
1832 auto CheckCSREncodingConflict = [&]() {
1833 auto Reg = RISCVSysReg::lookupSiFiveRegByEncoding(SysReg->Encoding);
1834 if (Reg && Reg->haveVendorRequiredFeatures(getSTI().getFeatureBits())) {
1835 Warning(S, "'" + Identifier + "' CSR is not available on the current " +
1836 "subtarget. Instead '" + Reg->Name +
1837 "' CSR will be used.");
1838 Operands.push_back(
1839 RISCVOperand::createSysReg(Reg->Name, S, Reg->Encoding));
1840 return true;
1841 }
1842 return false;
1843 };
1844
1845 // Accept a named SysReg if the required features are present.
1846 if (SysReg) {
1847 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))
1848 return Error(S, "system register use requires an option to be enabled");
1849 if (CheckCSREncodingConflict())
1850 return ParseStatus::Success;
1851 Operands.push_back(
1852 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1853 return ParseStatus::Success;
1854 }
1855
1856 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
1857 "operand must be a valid system register "
1858 "name or an integer in the range");
1859 }
1860 case AsmToken::Percent: {
1861 // Discard operand with modifier.
1862 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1863 }
1864 }
1865
1866 return ParseStatus::NoMatch;
1867}
1868
1869ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
1870 SMLoc S = getLoc();
1871
1872 // Parse special floats (inf/nan/min) representation.
1873 if (getTok().is(AsmToken::Identifier)) {
1874 StringRef Identifier = getTok().getIdentifier();
1875 if (Identifier.compare_insensitive("inf") == 0) {
1876 Operands.push_back(
1877 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
1878 getTok().getEndLoc(), isRV64()));
1879 } else if (Identifier.compare_insensitive("nan") == 0) {
1880 Operands.push_back(
1881 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
1882 getTok().getEndLoc(), isRV64()));
1883 } else if (Identifier.compare_insensitive("min") == 0) {
1884 Operands.push_back(
1885 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
1886 getTok().getEndLoc(), isRV64()));
1887 } else {
1888 return TokError("invalid floating point literal");
1889 }
1890
1891 Lex(); // Eat the token.
1892
1893 return ParseStatus::Success;
1894 }
1895
1896 // Handle negation, as that still comes through as a separate token.
1897 bool IsNegative = parseOptionalToken(AsmToken::Minus);
1898
1899 const AsmToken &Tok = getTok();
1900 if (!Tok.is(AsmToken::Real))
1901 return TokError("invalid floating point immediate");
1902
1903 // Parse FP representation.
1904 APFloat RealVal(APFloat::IEEEdouble());
1905 auto StatusOrErr =
1906 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
1907 if (errorToBool(StatusOrErr.takeError()))
1908 return TokError("invalid floating point representation");
1909
1910 if (IsNegative)
1911 RealVal.changeSign();
1912
1913 Operands.push_back(RISCVOperand::createFPImm(
1914 RealVal.bitcastToAPInt().getZExtValue(), S));
1915
1916 Lex(); // Eat the token.
1917
1918 return ParseStatus::Success;
1919}
1920
1921ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {
1922 SMLoc S = getLoc();
1923 SMLoc E;
1924 const MCExpr *Res;
1925
1926 switch (getLexer().getKind()) {
1927 default:
1928 return ParseStatus::NoMatch;
1929 case AsmToken::LParen:
1930 case AsmToken::Dot:
1931 case AsmToken::Minus:
1932 case AsmToken::Plus:
1933 case AsmToken::Exclaim:
1934 case AsmToken::Tilde:
1935 case AsmToken::Integer:
1936 case AsmToken::String:
1938 if (getParser().parseExpression(Res, E))
1939 return ParseStatus::Failure;
1940 break;
1941 case AsmToken::Percent:
1942 return parseOperandWithModifier(Operands);
1943 }
1944
1945 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1946 return ParseStatus::Success;
1947}
1948
1949ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1950 SMLoc S = getLoc();
1951 SMLoc E;
1952
1953 if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
1954 return ParseStatus::Failure;
1955
1956 if (getLexer().getKind() != AsmToken::Identifier)
1957 return Error(getLoc(), "expected valid identifier for operand modifier");
1958 StringRef Identifier = getParser().getTok().getIdentifier();
1961 return Error(getLoc(), "unrecognized operand modifier");
1962
1963 getParser().Lex(); // Eat the identifier
1964 if (parseToken(AsmToken::LParen, "expected '('"))
1965 return ParseStatus::Failure;
1966
1967 const MCExpr *SubExpr;
1968 if (getParser().parseParenExpression(SubExpr, E))
1969 return ParseStatus::Failure;
1970
1971 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
1972 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
1973 return ParseStatus::Success;
1974}
1975
1976ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1977 SMLoc S = getLoc();
1978 const MCExpr *Res;
1979
1980 if (getLexer().getKind() != AsmToken::Identifier)
1981 return ParseStatus::NoMatch;
1982
1984 AsmToken Tok = getLexer().getTok();
1985
1986 if (getParser().parseIdentifier(Identifier))
1987 return ParseStatus::Failure;
1988
1990
1991 if (Identifier.consume_back("@plt"))
1992 return Error(getLoc(), "'@plt' operand not valid for instruction");
1993
1994 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1995
1996 if (Sym->isVariable()) {
1997 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1998 if (!isa<MCSymbolRefExpr>(V)) {
1999 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
2000 return ParseStatus::NoMatch;
2001 }
2002 Res = V;
2003 } else
2005
2006 MCBinaryExpr::Opcode Opcode;
2007 switch (getLexer().getKind()) {
2008 default:
2009 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2010 return ParseStatus::Success;
2011 case AsmToken::Plus:
2012 Opcode = MCBinaryExpr::Add;
2013 getLexer().Lex();
2014 break;
2015 case AsmToken::Minus:
2016 Opcode = MCBinaryExpr::Sub;
2017 getLexer().Lex();
2018 break;
2019 }
2020
2021 const MCExpr *Expr;
2022 if (getParser().parseExpression(Expr, E))
2023 return ParseStatus::Failure;
2024 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
2025 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2026 return ParseStatus::Success;
2027}
2028
2029ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2030 SMLoc S = getLoc();
2031 const MCExpr *Res;
2032
2033 if (getLexer().getKind() != AsmToken::Identifier)
2034 return ParseStatus::NoMatch;
2035
2036 // Avoid parsing the register in `call rd, foo` as a call symbol.
2037 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
2038 return ParseStatus::NoMatch;
2039
2041 if (getParser().parseIdentifier(Identifier))
2042 return ParseStatus::Failure;
2043
2045
2047 if (Identifier.consume_back("@plt"))
2049
2050 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2052 Res = RISCVMCExpr::create(Res, Kind, getContext());
2053 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2054 return ParseStatus::Success;
2055}
2056
2057ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2058 SMLoc S = getLoc();
2059 SMLoc E;
2060 const MCExpr *Res;
2061
2062 if (getParser().parseExpression(Res, E))
2063 return ParseStatus::Failure;
2064
2065 if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
2066 cast<MCSymbolRefExpr>(Res)->getKind() ==
2067 MCSymbolRefExpr::VariantKind::VK_PLT)
2068 return Error(S, "operand must be a valid jump target");
2069
2070 Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
2071 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2072 return ParseStatus::Success;
2073}
2074
2075ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2076 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2077 // both being acceptable forms. When parsing `jal ra, foo` this function
2078 // will be called for the `ra` register operand in an attempt to match the
2079 // single-operand alias. parseJALOffset must fail for this case. It would
2080 // seem logical to try parse the operand using parseImmediate and return
2081 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2082 // the second form rather than the first). We can't do this as there's no
2083 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2084 // is an identifier and is followed by a comma.
2085 if (getLexer().is(AsmToken::Identifier) &&
2086 getLexer().peekTok().is(AsmToken::Comma))
2087 return ParseStatus::NoMatch;
2088
2089 return parseImmediate(Operands);
2090}
2091
2092bool RISCVAsmParser::parseVTypeToken(StringRef Identifier, VTypeState &State,
2093 unsigned &Sew, unsigned &Lmul,
2094 bool &Fractional, bool &TailAgnostic,
2095 bool &MaskAgnostic) {
2096 switch (State) {
2097 case VTypeState_SEW:
2098 if (!Identifier.consume_front("e"))
2099 break;
2100 if (Identifier.getAsInteger(10, Sew))
2101 break;
2102 if (!RISCVVType::isValidSEW(Sew))
2103 break;
2104 State = VTypeState_LMUL;
2105 return false;
2106 case VTypeState_LMUL: {
2107 if (!Identifier.consume_front("m"))
2108 break;
2109 Fractional = Identifier.consume_front("f");
2110 if (Identifier.getAsInteger(10, Lmul))
2111 break;
2112 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2113 break;
2114 State = VTypeState_TailPolicy;
2115 return false;
2116 }
2117 case VTypeState_TailPolicy:
2118 if (Identifier == "ta")
2119 TailAgnostic = true;
2120 else if (Identifier == "tu")
2121 TailAgnostic = false;
2122 else
2123 break;
2124 State = VTypeState_MaskPolicy;
2125 return false;
2126 case VTypeState_MaskPolicy:
2127 if (Identifier == "ma")
2128 MaskAgnostic = true;
2129 else if (Identifier == "mu")
2130 MaskAgnostic = false;
2131 else
2132 break;
2133 State = VTypeState_Done;
2134 return false;
2135 case VTypeState_Done:
2136 // Extra token?
2137 break;
2138 }
2139
2140 return true;
2141}
2142
2143ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2144 SMLoc S = getLoc();
2145
2146 unsigned Sew = 0;
2147 unsigned Lmul = 0;
2148 bool Fractional = false;
2149 bool TailAgnostic = false;
2150 bool MaskAgnostic = false;
2151
2152 VTypeState State = VTypeState_SEW;
2153
2154 if (getLexer().isNot(AsmToken::Identifier))
2155 return ParseStatus::NoMatch;
2156
2157 StringRef Identifier = getTok().getIdentifier();
2158
2159 if (parseVTypeToken(Identifier, State, Sew, Lmul, Fractional, TailAgnostic,
2160 MaskAgnostic))
2161 return ParseStatus::NoMatch;
2162
2163 getLexer().Lex();
2164
2165 while (parseOptionalToken(AsmToken::Comma)) {
2166 if (getLexer().isNot(AsmToken::Identifier))
2167 break;
2168
2169 Identifier = getTok().getIdentifier();
2170
2171 if (parseVTypeToken(Identifier, State, Sew, Lmul, Fractional, TailAgnostic,
2172 MaskAgnostic))
2173 break;
2174
2175 getLexer().Lex();
2176 }
2177
2178 if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {
2179 RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2180
2181 unsigned VTypeI =
2183 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2184 return ParseStatus::Success;
2185 }
2186
2187 return generateVTypeError(S);
2188}
2189
2190bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2191 return Error(
2192 ErrorLoc,
2193 "operand must be "
2194 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2195}
2196
2197ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2198 if (getLexer().isNot(AsmToken::Identifier))
2199 return ParseStatus::NoMatch;
2200
2201 StringRef Name = getLexer().getTok().getIdentifier();
2202 if (!Name.consume_back(".t"))
2203 return Error(getLoc(), "expected '.t' suffix");
2204 MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
2205
2206 if (!RegNo)
2207 return ParseStatus::NoMatch;
2208 if (RegNo != RISCV::V0)
2209 return ParseStatus::NoMatch;
2210 SMLoc S = getLoc();
2212 getLexer().Lex();
2213 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
2214 return ParseStatus::Success;
2215}
2216
2217ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2218 if (getLexer().isNot(AsmToken::Identifier))
2219 return ParseStatus::NoMatch;
2220
2221 StringRef Name = getLexer().getTok().getIdentifier();
2222 MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
2223
2224 if (!RegNo)
2225 return ParseStatus::NoMatch;
2226 SMLoc S = getLoc();
2228 getLexer().Lex();
2229 Operands.push_back(RISCVOperand::createReg(
2230 RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2231 return ParseStatus::Success;
2232}
2233
2234ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2235 if (getLexer().isNot(AsmToken::Identifier))
2236 return TokError(
2237 "operand must be a valid floating point rounding mode mnemonic");
2238
2239 StringRef Str = getLexer().getTok().getIdentifier();
2241
2242 if (FRM == RISCVFPRndMode::Invalid)
2243 return TokError(
2244 "operand must be a valid floating point rounding mode mnemonic");
2245
2246 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2247 Lex(); // Eat identifier token.
2248 return ParseStatus::Success;
2249}
2250
2251ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2252 const AsmToken &Tok = getLexer().getTok();
2253
2254 if (Tok.is(AsmToken::Integer)) {
2255 if (Tok.getIntVal() != 0)
2256 goto ParseFail;
2257
2258 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2259 Lex();
2260 return ParseStatus::Success;
2261 }
2262
2263 if (Tok.is(AsmToken::Identifier)) {
2264 StringRef Str = Tok.getIdentifier();
2265
2266 // Letters must be unique, taken from 'iorw', and in ascending order. This
2267 // holds as long as each individual character is one of 'iorw' and is
2268 // greater than the previous character.
2269 unsigned Imm = 0;
2270 bool Valid = true;
2271 char Prev = '\0';
2272 for (char c : Str) {
2273 switch (c) {
2274 default:
2275 Valid = false;
2276 break;
2277 case 'i':
2279 break;
2280 case 'o':
2282 break;
2283 case 'r':
2285 break;
2286 case 'w':
2288 break;
2289 }
2290
2291 if (c <= Prev) {
2292 Valid = false;
2293 break;
2294 }
2295 Prev = c;
2296 }
2297
2298 if (!Valid)
2299 goto ParseFail;
2300
2301 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2302 Lex();
2303 return ParseStatus::Success;
2304 }
2305
2306ParseFail:
2307 return TokError("operand must be formed of letters selected in-order from "
2308 "'iorw' or be 0");
2309}
2310
2311ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2312 if (parseToken(AsmToken::LParen, "expected '('"))
2313 return ParseStatus::Failure;
2314 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2315
2316 if (!parseRegister(Operands).isSuccess())
2317 return Error(getLoc(), "expected register");
2318
2319 if (parseToken(AsmToken::RParen, "expected ')'"))
2320 return ParseStatus::Failure;
2321 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2322
2323 return ParseStatus::Success;
2324}
2325
2326ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2327 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2328 // as one of their register operands, such as `(a0)`. This just denotes that
2329 // the register (in this case `a0`) contains a memory address.
2330 //
2331 // Normally, we would be able to parse these by putting the parens into the
2332 // instruction string. However, GNU as also accepts a zero-offset memory
2333 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2334 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2335 // do not accept an immediate operand, and we do not want to add a "dummy"
2336 // operand that is silently dropped.
2337 //
2338 // Instead, we use this custom parser. This will: allow (and discard) an
2339 // offset if it is zero; require (and discard) parentheses; and add only the
2340 // parsed register operand to `Operands`.
2341 //
2342 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2343 // which will only print the register surrounded by parentheses (which GNU as
2344 // also uses as its canonical representation for these operands).
2345 std::unique_ptr<RISCVOperand> OptionalImmOp;
2346
2347 if (getLexer().isNot(AsmToken::LParen)) {
2348 // Parse an Integer token. We do not accept arbritrary constant expressions
2349 // in the offset field (because they may include parens, which complicates
2350 // parsing a lot).
2351 int64_t ImmVal;
2352 SMLoc ImmStart = getLoc();
2353 if (getParser().parseIntToken(ImmVal,
2354 "expected '(' or optional integer offset"))
2355 return ParseStatus::Failure;
2356
2357 // Create a RISCVOperand for checking later (so the error messages are
2358 // nicer), but we don't add it to Operands.
2359 SMLoc ImmEnd = getLoc();
2360 OptionalImmOp =
2361 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
2362 ImmStart, ImmEnd, isRV64());
2363 }
2364
2365 if (parseToken(AsmToken::LParen,
2366 OptionalImmOp ? "expected '(' after optional integer offset"
2367 : "expected '(' or optional integer offset"))
2368 return ParseStatus::Failure;
2369
2370 if (!parseRegister(Operands).isSuccess())
2371 return Error(getLoc(), "expected register");
2372
2373 if (parseToken(AsmToken::RParen, "expected ')'"))
2374 return ParseStatus::Failure;
2375
2376 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2377 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2378 return Error(
2379 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2380 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2381
2382 return ParseStatus::Success;
2383}
2384
2385ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
2386 // Rlist: {ra [, s0[-sN]]}
2387 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2388 SMLoc S = getLoc();
2389
2390 if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
2391 return ParseStatus::Failure;
2392
2393 bool IsEABI = isRVE();
2394
2395 if (getLexer().isNot(AsmToken::Identifier))
2396 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2397
2398 StringRef RegName = getLexer().getTok().getIdentifier();
2399 MCRegister RegStart = matchRegisterNameHelper(IsEABI, RegName);
2400 MCRegister RegEnd;
2401 if (RegStart != RISCV::X1)
2402 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2403 getLexer().Lex();
2404
2405 // parse case like ,s0
2406 if (parseOptionalToken(AsmToken::Comma)) {
2407 if (getLexer().isNot(AsmToken::Identifier))
2408 return Error(getLoc(), "invalid register");
2409 StringRef RegName = getLexer().getTok().getIdentifier();
2410 RegStart = matchRegisterNameHelper(IsEABI, RegName);
2411 if (!RegStart)
2412 return Error(getLoc(), "invalid register");
2413 if (RegStart != RISCV::X8)
2414 return Error(getLoc(),
2415 "continuous register list must start from 's0' or 'x8'");
2416 getLexer().Lex(); // eat reg
2417 }
2418
2419 // parse case like -s1
2420 if (parseOptionalToken(AsmToken::Minus)) {
2421 StringRef EndName = getLexer().getTok().getIdentifier();
2422 // FIXME: the register mapping and checks of EABI is wrong
2423 RegEnd = matchRegisterNameHelper(IsEABI, EndName);
2424 if (!RegEnd)
2425 return Error(getLoc(), "invalid register");
2426 if (IsEABI && RegEnd != RISCV::X9)
2427 return Error(getLoc(), "contiguous register list of EABI can only be "
2428 "'s0-s1' or 'x8-x9' pair");
2429 getLexer().Lex();
2430 }
2431
2432 if (!IsEABI) {
2433 // parse extra part like ', x18[-x20]' for XRegList
2434 if (parseOptionalToken(AsmToken::Comma)) {
2435 if (RegEnd != RISCV::X9)
2436 return Error(
2437 getLoc(),
2438 "first contiguous registers pair of register list must be 'x8-x9'");
2439
2440 // parse ', x18' for extra part
2441 if (getLexer().isNot(AsmToken::Identifier))
2442 return Error(getLoc(), "invalid register");
2443 StringRef EndName = getLexer().getTok().getIdentifier();
2444 if (MatchRegisterName(EndName) != RISCV::X18)
2445 return Error(getLoc(),
2446 "second contiguous registers pair of register list "
2447 "must start from 'x18'");
2448 getLexer().Lex();
2449
2450 // parse '-x20' for extra part
2451 if (parseOptionalToken(AsmToken::Minus)) {
2452 if (getLexer().isNot(AsmToken::Identifier))
2453 return Error(getLoc(), "invalid register");
2454 EndName = getLexer().getTok().getIdentifier();
2455 if (MatchRegisterName(EndName) == RISCV::NoRegister)
2456 return Error(getLoc(), "invalid register");
2457 getLexer().Lex();
2458 }
2459 RegEnd = MatchRegisterName(EndName);
2460 }
2461 }
2462
2463 if (RegEnd == RISCV::X26)
2464 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2465 "x18-x26} is not supported");
2466
2467 if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
2468 return ParseStatus::Failure;
2469
2470 if (RegEnd == RISCV::NoRegister)
2471 RegEnd = RegStart;
2472
2473 auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
2474 if (Encode == 16)
2475 return Error(S, "invalid register list");
2476 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2477
2478 return ParseStatus::Success;
2479}
2480
2481ParseStatus RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) {
2482 (void)parseOptionalToken(AsmToken::Minus);
2483
2484 SMLoc S = getLoc();
2485 int64_t StackAdjustment = getLexer().getTok().getIntVal();
2486 unsigned Spimm = 0;
2487 unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
2488
2489 bool IsEABI = isRVE();
2490 if (!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI))
2491 return ParseStatus::NoMatch;
2492 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2493 getLexer().Lex();
2494 return ParseStatus::Success;
2495}
2496
2497/// Looks at a token type and creates the relevant operand from this
2498/// information, adding to Operands. If operand was parsed, returns false, else
2499/// true.
2500bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2501 // Check if the current operand has a custom associated parser, if so, try to
2502 // custom parse the operand, or fallback to the general approach.
2504 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
2505 if (Result.isSuccess())
2506 return false;
2507 if (Result.isFailure())
2508 return true;
2509
2510 // Attempt to parse token as a register.
2511 if (parseRegister(Operands, true).isSuccess())
2512 return false;
2513
2514 // Attempt to parse token as an immediate
2515 if (parseImmediate(Operands).isSuccess()) {
2516 // Parse memory base register if present
2517 if (getLexer().is(AsmToken::LParen))
2518 return !parseMemOpBaseReg(Operands).isSuccess();
2519 return false;
2520 }
2521
2522 // Finally we have exhausted all options and must declare defeat.
2523 Error(getLoc(), "unknown operand");
2524 return true;
2525}
2526
2527bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2528 StringRef Name, SMLoc NameLoc,
2530 // Ensure that if the instruction occurs when relaxation is enabled,
2531 // relocations are forced for the file. Ideally this would be done when there
2532 // is enough information to reliably determine if the instruction itself may
2533 // cause relaxations. Unfortunately instruction processing stage occurs in the
2534 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2535 // for the entire file.
2536 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2537 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2538 if (Assembler != nullptr) {
2539 RISCVAsmBackend &MAB =
2540 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
2541 MAB.setForceRelocs();
2542 }
2543 }
2544
2545 // First operand is token for instruction
2546 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
2547
2548 // If there are no more operands, then finish
2549 if (getLexer().is(AsmToken::EndOfStatement)) {
2550 getParser().Lex(); // Consume the EndOfStatement.
2551 return false;
2552 }
2553
2554 // Parse first operand
2555 if (parseOperand(Operands, Name))
2556 return true;
2557
2558 // Parse until end of statement, consuming commas between operands
2559 while (parseOptionalToken(AsmToken::Comma)) {
2560 // Parse next operand
2561 if (parseOperand(Operands, Name))
2562 return true;
2563 }
2564
2565 if (getParser().parseEOL("unexpected token")) {
2566 getParser().eatToEndOfStatement();
2567 return true;
2568 }
2569 return false;
2570}
2571
2572bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2575
2576 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2577 Kind = RE->getKind();
2578 Expr = RE->getSubExpr();
2579 }
2580
2581 MCValue Res;
2582 MCFixup Fixup;
2583 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2584 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
2585 return false;
2586}
2587
2588bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
2589 MCValue Res;
2590 MCFixup Fixup;
2591 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
2592 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
2593 Res.getSymB();
2594 }
2595 return false;
2596}
2597
2598ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
2599 StringRef IDVal = DirectiveID.getString();
2600
2601 if (IDVal == ".option")
2602 return parseDirectiveOption();
2603 if (IDVal == ".attribute")
2604 return parseDirectiveAttribute();
2605 if (IDVal == ".insn")
2606 return parseDirectiveInsn(DirectiveID.getLoc());
2607 if (IDVal == ".variant_cc")
2608 return parseDirectiveVariantCC();
2609
2610 return ParseStatus::NoMatch;
2611}
2612
2613bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
2614 bool FromOptionDirective) {
2615 for (auto Feature : RISCVFeatureKV)
2617 clearFeatureBits(Feature.Value, Feature.Key);
2618
2619 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2620 Arch, /*EnableExperimentalExtension=*/true,
2621 /*ExperimentalExtensionVersionCheck=*/true);
2622 if (!ParseResult) {
2623 std::string Buffer;
2624 raw_string_ostream OutputErrMsg(Buffer);
2625 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2626 OutputErrMsg << "invalid arch name '" << Arch << "', "
2627 << ErrMsg.getMessage();
2628 });
2629
2630 return Error(Loc, OutputErrMsg.str());
2631 }
2632 auto &ISAInfo = *ParseResult;
2633
2634 for (auto Feature : RISCVFeatureKV)
2635 if (ISAInfo->hasExtension(Feature.Key))
2636 setFeatureBits(Feature.Value, Feature.Key);
2637
2638 if (FromOptionDirective) {
2639 if (ISAInfo->getXLen() == 32 && isRV64())
2640 return Error(Loc, "bad arch string switching from rv64 to rv32");
2641 else if (ISAInfo->getXLen() == 64 && !isRV64())
2642 return Error(Loc, "bad arch string switching from rv32 to rv64");
2643 }
2644
2645 if (ISAInfo->getXLen() == 32)
2646 clearFeatureBits(RISCV::Feature64Bit, "64bit");
2647 else if (ISAInfo->getXLen() == 64)
2648 setFeatureBits(RISCV::Feature64Bit, "64bit");
2649 else
2650 return Error(Loc, "bad arch string " + Arch);
2651
2652 Result = ISAInfo->toString();
2653 return false;
2654}
2655
2656bool RISCVAsmParser::parseDirectiveOption() {
2657 MCAsmParser &Parser = getParser();
2658 // Get the option token.
2659 AsmToken Tok = Parser.getTok();
2660
2661 // At the moment only identifiers are supported.
2662 if (parseToken(AsmToken::Identifier, "expected identifier"))
2663 return true;
2664
2666
2667 if (Option == "push") {
2668 if (Parser.parseEOL())
2669 return true;
2670
2671 getTargetStreamer().emitDirectiveOptionPush();
2672 pushFeatureBits();
2673 return false;
2674 }
2675
2676 if (Option == "pop") {
2677 SMLoc StartLoc = Parser.getTok().getLoc();
2678 if (Parser.parseEOL())
2679 return true;
2680
2681 getTargetStreamer().emitDirectiveOptionPop();
2682 if (popFeatureBits())
2683 return Error(StartLoc, ".option pop with no .option push");
2684
2685 return false;
2686 }
2687
2688 if (Option == "arch") {
2690 do {
2691 if (Parser.parseComma())
2692 return true;
2693
2695 if (parseOptionalToken(AsmToken::Plus))
2696 Type = RISCVOptionArchArgType::Plus;
2697 else if (parseOptionalToken(AsmToken::Minus))
2698 Type = RISCVOptionArchArgType::Minus;
2699 else if (!Args.empty())
2700 return Error(Parser.getTok().getLoc(),
2701 "unexpected token, expected + or -");
2702 else
2703 Type = RISCVOptionArchArgType::Full;
2704
2705 if (Parser.getTok().isNot(AsmToken::Identifier))
2706 return Error(Parser.getTok().getLoc(),
2707 "unexpected token, expected identifier");
2708
2709 StringRef Arch = Parser.getTok().getString();
2710 SMLoc Loc = Parser.getTok().getLoc();
2711 Parser.Lex();
2712
2713 if (Type == RISCVOptionArchArgType::Full) {
2714 std::string Result;
2715 if (resetToArch(Arch, Loc, Result, true))
2716 return true;
2717
2718 Args.emplace_back(Type, Result);
2719 break;
2720 }
2721
2723 auto Ext = llvm::lower_bound(KVArray, Arch);
2724 if (Ext == KVArray.end() || StringRef(Ext->Key) != Arch ||
2726 if (isDigit(Arch.back()))
2727 return Error(
2728 Loc,
2729 "Extension version number parsing not currently implemented");
2730 return Error(Loc, "unknown extension feature");
2731 }
2732
2733 Args.emplace_back(Type, Ext->Key);
2734
2735 if (Type == RISCVOptionArchArgType::Plus) {
2736 FeatureBitset OldFeatureBits = STI->getFeatureBits();
2737
2738 setFeatureBits(Ext->Value, Ext->Key);
2739 auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());
2740 if (!ParseResult) {
2741 copySTI().setFeatureBits(OldFeatureBits);
2742 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
2743
2744 std::string Buffer;
2745 raw_string_ostream OutputErrMsg(Buffer);
2746 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2747 OutputErrMsg << ErrMsg.getMessage();
2748 });
2749
2750 return Error(Loc, OutputErrMsg.str());
2751 }
2752 } else {
2753 assert(Type == RISCVOptionArchArgType::Minus);
2754 // It is invalid to disable an extension that there are other enabled
2755 // extensions depend on it.
2756 // TODO: Make use of RISCVISAInfo to handle this
2757 for (auto Feature : KVArray) {
2758 if (getSTI().hasFeature(Feature.Value) &&
2759 Feature.Implies.test(Ext->Value))
2760 return Error(Loc,
2761 Twine("Can't disable ") + Ext->Key + " extension, " +
2762 Feature.Key + " extension requires " + Ext->Key +
2763 " extension be enabled");
2764 }
2765
2766 clearFeatureBits(Ext->Value, Ext->Key);
2767 }
2768 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
2769
2770 if (Parser.parseEOL())
2771 return true;
2772
2773 getTargetStreamer().emitDirectiveOptionArch(Args);
2774 return false;
2775 }
2776
2777 if (Option == "rvc") {
2778 if (Parser.parseEOL())
2779 return true;
2780
2781 getTargetStreamer().emitDirectiveOptionRVC();
2782 setFeatureBits(RISCV::FeatureStdExtC, "c");
2783 return false;
2784 }
2785
2786 if (Option == "norvc") {
2787 if (Parser.parseEOL())
2788 return true;
2789
2790 getTargetStreamer().emitDirectiveOptionNoRVC();
2791 clearFeatureBits(RISCV::FeatureStdExtC, "c");
2792 clearFeatureBits(RISCV::FeatureStdExtZca, "+zca");
2793 return false;
2794 }
2795
2796 if (Option == "pic") {
2797 if (Parser.parseEOL())
2798 return true;
2799
2800 getTargetStreamer().emitDirectiveOptionPIC();
2801 ParserOptions.IsPicEnabled = true;
2802 return false;
2803 }
2804
2805 if (Option == "nopic") {
2806 if (Parser.parseEOL())
2807 return true;
2808
2809 getTargetStreamer().emitDirectiveOptionNoPIC();
2810 ParserOptions.IsPicEnabled = false;
2811 return false;
2812 }
2813
2814 if (Option == "relax") {
2815 if (Parser.parseEOL())
2816 return true;
2817
2818 getTargetStreamer().emitDirectiveOptionRelax();
2819 setFeatureBits(RISCV::FeatureRelax, "relax");
2820 return false;
2821 }
2822
2823 if (Option == "norelax") {
2824 if (Parser.parseEOL())
2825 return true;
2826
2827 getTargetStreamer().emitDirectiveOptionNoRelax();
2828 clearFeatureBits(RISCV::FeatureRelax, "relax");
2829 return false;
2830 }
2831
2832 // Unknown option.
2833 Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
2834 "'rvc', 'norvc', 'arch', 'relax' or "
2835 "'norelax'");
2836 Parser.eatToEndOfStatement();
2837 return false;
2838}
2839
2840/// parseDirectiveAttribute
2841/// ::= .attribute expression ',' ( expression | "string" )
2842/// ::= .attribute identifier ',' ( expression | "string" )
2843bool RISCVAsmParser::parseDirectiveAttribute() {
2844 MCAsmParser &Parser = getParser();
2845 int64_t Tag;
2846 SMLoc TagLoc;
2847 TagLoc = Parser.getTok().getLoc();
2848 if (Parser.getTok().is(AsmToken::Identifier)) {
2849 StringRef Name = Parser.getTok().getIdentifier();
2850 std::optional<unsigned> Ret =
2852 if (!Ret)
2853 return Error(TagLoc, "attribute name not recognised: " + Name);
2854 Tag = *Ret;
2855 Parser.Lex();
2856 } else {
2857 const MCExpr *AttrExpr;
2858
2859 TagLoc = Parser.getTok().getLoc();
2860 if (Parser.parseExpression(AttrExpr))
2861 return true;
2862
2863 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
2864 if (check(!CE, TagLoc, "expected numeric constant"))
2865 return true;
2866
2867 Tag = CE->getValue();
2868 }
2869
2870 if (Parser.parseComma())
2871 return true;
2872
2873 StringRef StringValue;
2874 int64_t IntegerValue = 0;
2875 bool IsIntegerValue = true;
2876
2877 // RISC-V attributes have a string value if the tag number is odd
2878 // and an integer value if the tag number is even.
2879 if (Tag % 2)
2880 IsIntegerValue = false;
2881
2882 SMLoc ValueExprLoc = Parser.getTok().getLoc();
2883 if (IsIntegerValue) {
2884 const MCExpr *ValueExpr;
2885 if (Parser.parseExpression(ValueExpr))
2886 return true;
2887
2888 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
2889 if (!CE)
2890 return Error(ValueExprLoc, "expected numeric constant");
2891 IntegerValue = CE->getValue();
2892 } else {
2893 if (Parser.getTok().isNot(AsmToken::String))
2894 return Error(Parser.getTok().getLoc(), "expected string constant");
2895
2896 StringValue = Parser.getTok().getStringContents();
2897 Parser.Lex();
2898 }
2899
2900 if (Parser.parseEOL())
2901 return true;
2902
2903 if (IsIntegerValue)
2904 getTargetStreamer().emitAttribute(Tag, IntegerValue);
2905 else if (Tag != RISCVAttrs::ARCH)
2906 getTargetStreamer().emitTextAttribute(Tag, StringValue);
2907 else {
2908 std::string Result;
2909 if (resetToArch(StringValue, ValueExprLoc, Result, false))
2910 return true;
2911
2912 // Then emit the arch string.
2913 getTargetStreamer().emitTextAttribute(Tag, Result);
2914 }
2915
2916 return false;
2917}
2918
2919bool isValidInsnFormat(StringRef Format, bool AllowC) {
2920 return StringSwitch<bool>(Format)
2921 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
2922 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
2923 .Default(false);
2924}
2925
2926/// parseDirectiveInsn
2927/// ::= .insn [ format encoding, (operands (, operands)*) ]
2928bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
2929 MCAsmParser &Parser = getParser();
2930
2931 // Expect instruction format as identifier.
2933 SMLoc ErrorLoc = Parser.getTok().getLoc();
2934 if (Parser.parseIdentifier(Format))
2935 return Error(ErrorLoc, "expected instruction format");
2936
2937 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
2938 getSTI().hasFeature(RISCV::FeatureStdExtZca);
2939 if (!isValidInsnFormat(Format, AllowC))
2940 return Error(ErrorLoc, "invalid instruction format");
2941
2942 std::string FormatName = (".insn_" + Format).str();
2943
2946
2947 if (ParseInstruction(Info, FormatName, L, Operands))
2948 return true;
2949
2950 unsigned Opcode;
2952 return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
2953 ErrorInfo,
2954 /*MatchingInlineAsm=*/false);
2955}
2956
2957/// parseDirectiveVariantCC
2958/// ::= .variant_cc symbol
2959bool RISCVAsmParser::parseDirectiveVariantCC() {
2961 if (getParser().parseIdentifier(Name))
2962 return TokError("expected symbol name");
2963 if (parseEOL())
2964 return true;
2965 getTargetStreamer().emitDirectiveVariantCC(
2966 *getContext().getOrCreateSymbol(Name));
2967 return false;
2968}
2969
2970void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
2971 MCInst CInst;
2972 bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
2973 if (Res)
2974 ++RISCVNumInstrsCompressed;
2975 S.emitInstruction((Res ? CInst : Inst), getSTI());
2976}
2977
2978void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
2979 MCStreamer &Out) {
2981 RISCVMatInt::generateInstSeq(Value, getSTI().getFeatureBits());
2982
2983 MCRegister SrcReg = RISCV::X0;
2984 for (const RISCVMatInt::Inst &Inst : Seq) {
2985 switch (Inst.getOpndKind()) {
2986 case RISCVMatInt::Imm:
2987 emitToStreamer(Out,
2988 MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addImm(Inst.getImm()));
2989 break;
2990 case RISCVMatInt::RegX0:
2991 emitToStreamer(
2992 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
2993 RISCV::X0));
2994 break;
2996 emitToStreamer(
2997 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
2998 SrcReg));
2999 break;
3001 emitToStreamer(
3002 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addImm(
3003 Inst.getImm()));
3004 break;
3005 }
3006
3007 // Only the first instruction has X0 as its source.
3008 SrcReg = DestReg;
3009 }
3010}
3011
3012void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
3013 const MCExpr *Symbol,
3015 unsigned SecondOpcode, SMLoc IDLoc,
3016 MCStreamer &Out) {
3017 // A pair of instructions for PC-relative addressing; expands to
3018 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3019 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3020 MCContext &Ctx = getContext();
3021
3022 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3023 Out.emitLabel(TmpLabel);
3024
3025 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
3026 emitToStreamer(
3027 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
3028
3029 const MCExpr *RefToLinkTmpLabel =
3032
3033 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3034 .addOperand(DestReg)
3035 .addOperand(TmpReg)
3036 .addExpr(RefToLinkTmpLabel));
3037}
3038
3039void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3040 MCStreamer &Out) {
3041 // The load local address pseudo-instruction "lla" is used in PC-relative
3042 // addressing of local symbols:
3043 // lla rdest, symbol
3044 // expands to
3045 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3046 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3047 MCOperand DestReg = Inst.getOperand(0);
3048 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3049 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3050 RISCV::ADDI, IDLoc, Out);
3051}
3052
3053void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3054 MCStreamer &Out) {
3055 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3056 // addressing of global symbols:
3057 // lga rdest, symbol
3058 // expands to
3059 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3060 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3061 MCOperand DestReg = Inst.getOperand(0);
3062 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3063 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3064 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
3065 SecondOpcode, IDLoc, Out);
3066}
3067
3068void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3069 MCStreamer &Out) {
3070 // The load address pseudo-instruction "la" is used in PC-relative and
3071 // GOT-indirect addressing of global symbols:
3072 // la rdest, symbol
3073 // is an alias for either (for non-PIC)
3074 // lla rdest, symbol
3075 // or (for PIC)
3076 // lga rdest, symbol
3077 if (ParserOptions.IsPicEnabled)
3078 emitLoadGlobalAddress(Inst, IDLoc, Out);
3079 else
3080 emitLoadLocalAddress(Inst, IDLoc, Out);
3081}
3082
3083void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3084 MCStreamer &Out) {
3085 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3086 // initial-exec TLS model addressing of global symbols:
3087 // la.tls.ie rdest, symbol
3088 // expands to
3089 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3090 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3091 MCOperand DestReg = Inst.getOperand(0);
3092 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3093 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3094 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
3095 SecondOpcode, IDLoc, Out);
3096}
3097
3098void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3099 MCStreamer &Out) {
3100 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3101 // global-dynamic TLS model addressing of global symbols:
3102 // la.tls.gd rdest, symbol
3103 // expands to
3104 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3105 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3106 MCOperand DestReg = Inst.getOperand(0);
3107 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3108 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
3109 RISCV::ADDI, IDLoc, Out);
3110}
3111
3112void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3113 SMLoc IDLoc, MCStreamer &Out,
3114 bool HasTmpReg) {
3115 // The load/store pseudo-instruction does a pc-relative load with
3116 // a symbol.
3117 //
3118 // The expansion looks like this
3119 //
3120 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3121 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3122 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3123 MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
3124 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3125 MCOperand TmpReg = Inst.getOperand(0);
3126 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3127 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3128 Opcode, IDLoc, Out);
3129}
3130
3131void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3132 int64_t Width, SMLoc IDLoc,
3133 MCStreamer &Out) {
3134 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3135 // amounts dependent on the XLEN.
3136 //
3137 // The expansion looks like this
3138 //
3139 // SLLI rd, rs, XLEN - Width
3140 // SR[A|R]I rd, rd, XLEN - Width
3141 MCOperand DestReg = Inst.getOperand(0);
3142 MCOperand SourceReg = Inst.getOperand(1);
3143
3144 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3145 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3146
3147 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3148
3149 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3150 .addOperand(DestReg)
3151 .addOperand(SourceReg)
3152 .addImm(ShAmt));
3153
3154 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3155 .addOperand(DestReg)
3156 .addOperand(DestReg)
3157 .addImm(ShAmt));
3158}
3159
3160void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3161 MCStreamer &Out) {
3162 if (Inst.getNumOperands() == 3) {
3163 // unmasked va >= x
3164 //
3165 // pseudoinstruction: vmsge{u}.vx vd, va, x
3166 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3167 emitToStreamer(Out, MCInstBuilder(Opcode)
3168 .addOperand(Inst.getOperand(0))
3169 .addOperand(Inst.getOperand(1))
3170 .addOperand(Inst.getOperand(2))
3171 .addReg(RISCV::NoRegister));
3172 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3173 .addOperand(Inst.getOperand(0))
3174 .addOperand(Inst.getOperand(0))
3175 .addOperand(Inst.getOperand(0)));
3176 } else if (Inst.getNumOperands() == 4) {
3177 // masked va >= x, vd != v0
3178 //
3179 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3180 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3181 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3182 "The destination register should not be V0.");
3183 emitToStreamer(Out, MCInstBuilder(Opcode)
3184 .addOperand(Inst.getOperand(0))
3185 .addOperand(Inst.getOperand(1))
3186 .addOperand(Inst.getOperand(2))
3187 .addOperand(Inst.getOperand(3)));
3188 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3189 .addOperand(Inst.getOperand(0))
3190 .addOperand(Inst.getOperand(0))
3191 .addReg(RISCV::V0));
3192 } else if (Inst.getNumOperands() == 5 &&
3193 Inst.getOperand(0).getReg() == RISCV::V0) {
3194 // masked va >= x, vd == v0
3195 //
3196 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3197 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3198 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3199 "The destination register should be V0.");
3200 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3201 "The temporary vector register should not be V0.");
3202 emitToStreamer(Out, MCInstBuilder(Opcode)
3203 .addOperand(Inst.getOperand(1))
3204 .addOperand(Inst.getOperand(2))
3205 .addOperand(Inst.getOperand(3))
3206 .addReg(RISCV::NoRegister));
3207 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3208 .addOperand(Inst.getOperand(0))
3209 .addOperand(Inst.getOperand(0))
3210 .addOperand(Inst.getOperand(1)));
3211 } else if (Inst.getNumOperands() == 5) {
3212 // masked va >= x, any vd
3213 //
3214 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3215 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3216 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3217 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3218 "The temporary vector register should not be V0.");
3219 emitToStreamer(Out, MCInstBuilder(Opcode)
3220 .addOperand(Inst.getOperand(1))
3221 .addOperand(Inst.getOperand(2))
3222 .addOperand(Inst.getOperand(3))
3223 .addReg(RISCV::NoRegister));
3224 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3225 .addOperand(Inst.getOperand(1))
3226 .addReg(RISCV::V0)
3227 .addOperand(Inst.getOperand(1)));
3228 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3229 .addOperand(Inst.getOperand(0))
3230 .addOperand(Inst.getOperand(0))
3231 .addReg(RISCV::V0));
3232 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3233 .addOperand(Inst.getOperand(0))
3234 .addOperand(Inst.getOperand(1))
3235 .addOperand(Inst.getOperand(0)));
3236 }
3237}
3238
3239bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3241 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
3242 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
3243 if (Inst.getOperand(2).getReg() != RISCV::X4) {
3244 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3245 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
3246 "%tprel_add modifier");
3247 }
3248
3249 return false;
3250}
3251
3252std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3253 return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
3254 llvm::SMLoc());
3255}
3256
3257std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3258 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3259 llvm::SMLoc());
3260}
3261
3262std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3263 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3264 llvm::SMLoc());
3265}
3266
3267bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3269 unsigned Opcode = Inst.getOpcode();
3270
3271 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3272 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3273 unsigned DestReg = Inst.getOperand(0).getReg();
3274 unsigned TempReg = Inst.getOperand(1).getReg();
3275 if (DestReg == TempReg) {
3276 SMLoc Loc = Operands.back()->getStartLoc();
3277 return Error(Loc, "The temporary vector register cannot be the same as "
3278 "the destination register.");
3279 }
3280 }
3281
3282 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3283 Opcode == RISCV::TH_LWD) {
3284 unsigned Rd1 = Inst.getOperand(0).getReg();
3285 unsigned Rd2 = Inst.getOperand(1).getReg();
3286 unsigned Rs1 = Inst.getOperand(2).getReg();
3287 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3288 if (Rs1 == Rd1 && Rs1 == Rd2) {
3289 SMLoc Loc = Operands[1]->getStartLoc();
3290 return Error(Loc, "The source register and destination registers "
3291 "cannot be equal.");
3292 }
3293 }
3294
3295 if (Opcode == RISCV::CM_MVSA01) {
3296 unsigned Rd1 = Inst.getOperand(0).getReg();
3297 unsigned Rd2 = Inst.getOperand(1).getReg();
3298 if (Rd1 == Rd2) {
3299 SMLoc Loc = Operands[1]->getStartLoc();
3300 return Error(Loc, "'rs1' and 'rs2' must be different.");
3301 }
3302 }
3303
3304 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3305 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3306 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3307 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3308 // depending on the data width.
3309 if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
3310 SMLoc Loc = Operands.back()->getStartLoc();
3311 return Error(Loc, "Operand must be constant 3.");
3312 } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
3313 SMLoc Loc = Operands.back()->getStartLoc();
3314 return Error(Loc, "Operand must be constant 4.");
3315 }
3316
3317 bool IsAMOCAS_D = Opcode == RISCV::AMOCAS_D || Opcode == RISCV::AMOCAS_D_AQ ||
3318 Opcode == RISCV::AMOCAS_D_RL ||
3319 Opcode == RISCV::AMOCAS_D_AQ_RL;
3320 bool IsAMOCAS_Q = Opcode == RISCV::AMOCAS_Q || Opcode == RISCV::AMOCAS_Q_AQ ||
3321 Opcode == RISCV::AMOCAS_Q_RL ||
3322 Opcode == RISCV::AMOCAS_Q_AQ_RL;
3323 if ((!isRV64() && IsAMOCAS_D) || IsAMOCAS_Q) {
3324 unsigned Rd = Inst.getOperand(0).getReg();
3325 unsigned Rs2 = Inst.getOperand(2).getReg();
3326 assert(Rd >= RISCV::X0 && Rd <= RISCV::X31);
3327 if ((Rd - RISCV::X0) % 2 != 0) {
3328 SMLoc Loc = Operands[1]->getStartLoc();
3329 return Error(Loc, "The destination register must be even.");
3330 }
3331 assert(Rs2 >= RISCV::X0 && Rs2 <= RISCV::X31);
3332 if ((Rs2 - RISCV::X0) % 2 != 0) {
3333 SMLoc Loc = Operands[2]->getStartLoc();
3334 return Error(Loc, "The source register must be even.");
3335 }
3336 }
3337
3338 const MCInstrDesc &MCID = MII.get(Opcode);
3339 if (!(MCID.TSFlags & RISCVII::ConstraintMask))
3340 return false;
3341
3342 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3343 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3344 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3345 unsigned VCIXDst = Inst.getOperand(0).getReg();
3346 SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
3347 if (MCID.TSFlags & RISCVII::VS1Constraint) {
3348 unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3349 if (VCIXDst == VCIXRs1)
3350 return Error(VCIXDstLoc, "The destination vector register group cannot"
3351 " overlap the source vector register group.");
3352 }
3353 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3354 unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
3355 if (VCIXDst == VCIXRs2)
3356 return Error(VCIXDstLoc, "The destination vector register group cannot"
3357 " overlap the source vector register group.");
3358 }
3359 return false;
3360 }
3361
3362 unsigned DestReg = Inst.getOperand(0).getReg();
3363 unsigned Offset = 0;
3364 int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
3365 if (TiedOp == 0)
3366 Offset = 1;
3367
3368 // Operands[1] will be the first operand, DestReg.
3369 SMLoc Loc = Operands[1]->getStartLoc();
3370 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3371 unsigned CheckReg = Inst.getOperand(Offset + 1).getReg();
3372 if (DestReg == CheckReg)
3373 return Error(Loc, "The destination vector register group cannot overlap"
3374 " the source vector register group.");
3375 }
3376 if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
3377 unsigned CheckReg = Inst.getOperand(Offset + 2).getReg();
3378 if (DestReg == CheckReg)
3379 return Error(Loc, "The destination vector register group cannot overlap"
3380 " the source vector register group.");
3381 }
3382 if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3383 // vadc, vsbc are special cases. These instructions have no mask register.
3384 // The destination register could not be V0.
3385 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3386 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3387 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3388 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3389 Opcode == RISCV::VMERGE_VXM)
3390 return Error(Loc, "The destination vector register group cannot be V0.");
3391
3392 // Regardless masked or unmasked version, the number of operands is the
3393 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3394 // actually. We need to check the last operand to ensure whether it is
3395 // masked or not.
3396 unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3397 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
3398 "Unexpected register for mask operand");
3399
3400 if (DestReg == CheckReg)
3401 return Error(Loc, "The destination vector register group cannot overlap"
3402 " the mask register.");
3403 }
3404 return false;
3405}
3406
3407bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
3409 MCStreamer &Out) {
3410 Inst.setLoc(IDLoc);
3411
3412 switch (Inst.getOpcode()) {
3413 default:
3414 break;
3415 case RISCV::PseudoLLAImm:
3416 case RISCV::PseudoLAImm:
3417 case RISCV::PseudoLI: {
3418 MCRegister Reg = Inst.getOperand(0).getReg();
3419 const MCOperand &Op1 = Inst.getOperand(1);
3420 if (Op1.isExpr()) {
3421 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3422 // Just convert to an addi. This allows compatibility with gas.
3423 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
3424 .addReg(Reg)
3425 .addReg(RISCV::X0)
3426 .addExpr(Op1.getExpr()));
3427 return false;
3428 }
3429 int64_t Imm = Inst.getOperand(1).getImm();
3430 // On RV32 the immediate here can either be a signed or an unsigned
3431 // 32-bit number. Sign extension has to be performed to ensure that Imm
3432 // represents the expected signed 64-bit number.
3433 if (!isRV64())
3434 Imm = SignExtend64<32>(Imm);
3435 emitLoadImm(Reg, Imm, Out);
3436 return false;
3437 }
3438 case RISCV::PseudoLLA:
3439 emitLoadLocalAddress(Inst, IDLoc, Out);
3440 return false;
3441 case RISCV::PseudoLGA:
3442 emitLoadGlobalAddress(Inst, IDLoc, Out);
3443 return false;
3444 case RISCV::PseudoLA:
3445 emitLoadAddress(Inst, IDLoc, Out);
3446 return false;
3447 case RISCV::PseudoLA_TLS_IE:
3448 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3449 return false;
3450 case RISCV::PseudoLA_TLS_GD:
3451 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3452 return false;
3453 case RISCV::PseudoLB:
3454 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
3455 return false;
3456 case RISCV::PseudoLBU:
3457 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
3458 return false;
3459 case RISCV::PseudoLH:
3460 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
3461 return false;
3462 case RISCV::PseudoLHU:
3463 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
3464 return false;
3465 case RISCV::PseudoLW:
3466 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
3467 return false;
3468 case RISCV::PseudoLWU:
3469 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
3470 return false;
3471 case RISCV::PseudoLD:
3472 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
3473 return false;
3474 case RISCV::PseudoFLH:
3475 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3476 return false;
3477 case RISCV::PseudoFLW:
3478 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
3479 return false;
3480 case RISCV::PseudoFLD:
3481 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
3482 return false;
3483 case RISCV::PseudoSB:
3484 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
3485 return false;
3486 case RISCV::PseudoSH:
3487 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
3488 return false;
3489 case RISCV::PseudoSW:
3490 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
3491 return false;
3492 case RISCV::PseudoSD:
3493 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
3494 return false;
3495 case RISCV::PseudoFSH:
3496 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3497 return false;
3498 case RISCV::PseudoFSW:
3499 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
3500 return false;
3501 case RISCV::PseudoFSD:
3502 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
3503 return false;
3504 case RISCV::PseudoAddTPRel:
3505 if (checkPseudoAddTPRel(Inst, Operands))
3506 return true;
3507 break;
3508 case RISCV::PseudoSEXT_B:
3509 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3510 return false;
3511 case RISCV::PseudoSEXT_H:
3512 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3513 return false;
3514 case RISCV::PseudoZEXT_H:
3515 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3516 return false;
3517 case RISCV::PseudoZEXT_W:
3518 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3519 return false;
3520 case RISCV::PseudoVMSGEU_VX:
3521 case RISCV::PseudoVMSGEU_VX_M:
3522 case RISCV::PseudoVMSGEU_VX_M_T:
3523 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3524 return false;
3525 case RISCV::PseudoVMSGE_VX:
3526 case RISCV::PseudoVMSGE_VX_M:
3527 case RISCV::PseudoVMSGE_VX_M_T:
3528 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3529 return false;
3530 case RISCV::PseudoVMSGE_VI:
3531 case RISCV::PseudoVMSLT_VI: {
3532 // These instructions are signed and so is immediate so we can subtract one
3533 // and change the opcode.
3534 int64_t Imm = Inst.getOperand(2).getImm();
3535 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3536 : RISCV::VMSLE_VI;
3537 emitToStreamer(Out, MCInstBuilder(Opc)
3538 .addOperand(Inst.getOperand(0))
3539 .addOperand(Inst.getOperand(1))
3540 .addImm(Imm - 1)
3541 .addOperand(Inst.getOperand(3)));
3542 return false;
3543 }
3544 case RISCV::PseudoVMSGEU_VI:
3545 case RISCV::PseudoVMSLTU_VI: {
3546 int64_t Imm = Inst.getOperand(2).getImm();
3547 // Unsigned comparisons are tricky because the immediate is signed. If the
3548 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3549 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3550 // vmsne v0, v1, v1 which is always false.
3551 if (Imm == 0) {
3552 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3553 ? RISCV::VMSEQ_VV
3554 : RISCV::VMSNE_VV;
3555 emitToStreamer(Out, MCInstBuilder(Opc)
3556 .addOperand(Inst.getOperand(0))
3557 .addOperand(Inst.getOperand(1))
3558 .addOperand(Inst.getOperand(1))
3559 .addOperand(Inst.getOperand(3)));
3560 } else {
3561 // Other immediate values can subtract one like signed.
3562 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3563 ? RISCV::VMSGTU_VI
3564 : RISCV::VMSLEU_VI;
3565 emitToStreamer(Out, MCInstBuilder(Opc)
3566 .addOperand(Inst.getOperand(0))
3567 .addOperand(Inst.getOperand(1))
3568 .addImm(Imm - 1)
3569 .addOperand(Inst.getOperand(3)));
3570 }
3571
3572 return false;
3573 }
3574 }
3575
3576 emitToStreamer(Out, Inst);
3577 return false;
3578}
3579
3583}
static const char * getSubtargetFeatureName(uint64_t Val)
static unsigned MatchRegisterName(StringRef Name)
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static unsigned 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
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
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:468
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
#define check(cond)
#define RegName(no)
static LVOptions Options
Definition: LVOptions.cpp:25
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
unsigned Reg
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
PowerPC TLS Dynamic Call Fixup
bool isValidInsnFormat(StringRef Format, bool AllowC)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser()
static MCRegister matchRegisterNameHelper(bool IsRVE, StringRef Name)
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)
bool TailAgnostic
bool MaskAgnostic
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
This file implements the SmallBitVector class.
This file defines the SmallString 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:167
This file contains some functions that are useful when dealing with strings.
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
Class for arbitrary precision integers.
Definition: APInt.h:76
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
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:352
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.
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 MCContext & getContext()=0
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:183
@ Sub
Subtraction.
Definition: MCExpr.h:509
@ Add
Addition.
Definition: MCExpr.h:487
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:450
MCSymbol * createNamedTempSymbol()
Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.
Definition: MCContext.cpp:324
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:802
ExprKind getKind() const
Definition: MCExpr.h:81
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:70
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
Definition: MCInstBuilder.h:31
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:37
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
unsigned getNumOperands() const
Definition: MCInst.h:208
void setLoc(SMLoc loc)
Definition: MCInst.h:203
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
ArrayRef< MCOperandInfo > operands() const
Definition: MCInstrDesc.h:239
unsigned short NumOperands
Definition: MCInstrDesc.h:206
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:36
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
int64_t getImm() const
Definition: MCInst.h:80
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
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
Streaming machine code generation interface.
Definition: MCStreamer.h:212
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:424
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:304
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:389
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.
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
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...
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual unsigned checkTargetMatchPredicate(MCInst &Inst)
checkTargetMatchPredicate - Validate the instruction match against any complex target predicates not ...
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
Target specific streamer interface.
Definition: MCStreamer.h:93
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
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 bool isSupportedExtension(StringRef Ext)
static llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true, bool IgnoreUnknown=false)
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:31
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:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
This class wraps a string in an Error.
Definition: Error.h:1221
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
char back() const
back - Get the last character in the string.
Definition: StringRef.h:146
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:642
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
const CustomOperand< const MCSubtargetInfo & > Msg[]
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.
InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures)
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, bool IsEABI)
void printSpimm(int64_t Spimm, raw_ostream &OS)
@ 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:445
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:1071
@ Offset
Definition: DWP.cpp:440
@ Length
Definition: DWP.cpp:440
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:228
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:131
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:970
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:1946
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:166
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.