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