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