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