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