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