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_InvalidSImm5Plus1: {
1685 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1686 (1 << 4),
1687 "immediate must be in the range");
1688 }
1689 case Match_InvalidSImm26:
1690 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 25),
1691 (1 << 25) - 1);
1692 case Match_InvalidRlist: {
1693 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1694 return Error(
1695 ErrorLoc,
1696 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1697 }
1698 case Match_InvalidStackAdj: {
1699 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1700 return Error(
1701 ErrorLoc,
1702 "stack adjustment is invalid for this instruction and register list; "
1703 "refer to Zc spec for a detailed range of stack adjustment");
1704 }
1705 case Match_InvalidRnumArg: {
1706 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1707 }
1708 case Match_InvalidRegReg: {
1709 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1710 return Error(ErrorLoc, "operands must be register and register");
1711 }
1712 }
1713
1714 llvm_unreachable("Unknown match type detected!");
1715}
1716
1717// Attempts to match Name as a register (either using the default name or
1718// alternative ABI names), returning the matching register. Upon failure,
1719// returns a non-valid MCRegister. If IsRVE, then registers x16-x31 will be
1720// rejected.
1721MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
1723 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1724 // match always matches the 64-bit variant, and not the 16/32-bit one.
1725 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1726 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1727 // The default FPR register class is based on the tablegen enum ordering.
1728 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1729 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1730 if (!Reg)
1732 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1733 Reg = MCRegister();
1734 return Reg;
1735}
1736
1737bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1738 SMLoc &EndLoc) {
1739 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1740 return Error(StartLoc, "invalid register name");
1741 return false;
1742}
1743
1744ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1745 SMLoc &EndLoc) {
1746 const AsmToken &Tok = getParser().getTok();
1747 StartLoc = Tok.getLoc();
1748 EndLoc = Tok.getEndLoc();
1749 StringRef Name = getLexer().getTok().getIdentifier();
1750
1752 if (!Reg)
1753 return ParseStatus::NoMatch;
1754
1755 getParser().Lex(); // Eat identifier token.
1756 return ParseStatus::Success;
1757}
1758
1759ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1760 bool AllowParens) {
1761 SMLoc FirstS = getLoc();
1762 bool HadParens = false;
1763 AsmToken LParen;
1764
1765 // If this is an LParen and a parenthesised register name is allowed, parse it
1766 // atomically.
1767 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1768 AsmToken Buf[2];
1769 size_t ReadCount = getLexer().peekTokens(Buf);
1770 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1771 HadParens = true;
1772 LParen = getParser().getTok();
1773 getParser().Lex(); // Eat '('
1774 }
1775 }
1776
1777 switch (getLexer().getKind()) {
1778 default:
1779 if (HadParens)
1780 getLexer().UnLex(LParen);
1781 return ParseStatus::NoMatch;
1783 StringRef Name = getLexer().getTok().getIdentifier();
1785
1786 if (!Reg) {
1787 if (HadParens)
1788 getLexer().UnLex(LParen);
1789 return ParseStatus::NoMatch;
1790 }
1791 if (HadParens)
1792 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1793 SMLoc S = getLoc();
1795 getLexer().Lex();
1796 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
1797 }
1798
1799 if (HadParens) {
1800 getParser().Lex(); // Eat ')'
1801 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1802 }
1803
1804 return ParseStatus::Success;
1805}
1806
1807ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1808 SMLoc S = getLoc();
1809 SMLoc E;
1810 const MCExpr *Res;
1811
1812 switch (getLexer().getKind()) {
1813 default:
1814 return ParseStatus::NoMatch;
1815 case AsmToken::LParen:
1816 case AsmToken::Minus:
1817 case AsmToken::Plus:
1818 case AsmToken::Exclaim:
1819 case AsmToken::Tilde:
1820 case AsmToken::Integer:
1821 case AsmToken::String: {
1822 if (getParser().parseExpression(Res, E))
1823 return ParseStatus::Failure;
1824
1825 auto *CE = dyn_cast<MCConstantExpr>(Res);
1826 if (CE) {
1827 int64_t Imm = CE->getValue();
1828 if (isUInt<7>(Imm)) {
1829 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1830 return ParseStatus::Success;
1831 }
1832 }
1833
1834 break;
1835 }
1836 case AsmToken::Identifier: {
1838 if (getParser().parseIdentifier(Identifier))
1839 return ParseStatus::Failure;
1840
1841 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1842 if (Opcode) {
1843 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1844 "Unexpected opcode");
1845 Res = MCConstantExpr::create(Opcode->Value, getContext());
1847 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1848 return ParseStatus::Success;
1849 }
1850
1851 break;
1852 }
1853 case AsmToken::Percent:
1854 break;
1855 }
1856
1857 return generateImmOutOfRangeError(
1858 S, 0, 127,
1859 "opcode must be a valid opcode name or an immediate in the range");
1860}
1861
1862ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
1863 SMLoc S = getLoc();
1864 SMLoc E;
1865 const MCExpr *Res;
1866
1867 switch (getLexer().getKind()) {
1868 default:
1869 return ParseStatus::NoMatch;
1870 case AsmToken::LParen:
1871 case AsmToken::Minus:
1872 case AsmToken::Plus:
1873 case AsmToken::Exclaim:
1874 case AsmToken::Tilde:
1875 case AsmToken::Integer:
1876 case AsmToken::String: {
1877 if (getParser().parseExpression(Res, E))
1878 return ParseStatus::Failure;
1879
1880 auto *CE = dyn_cast<MCConstantExpr>(Res);
1881 if (CE) {
1882 int64_t Imm = CE->getValue();
1883 if (Imm >= 0 && Imm <= 2) {
1884 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1885 return ParseStatus::Success;
1886 }
1887 }
1888
1889 break;
1890 }
1891 case AsmToken::Identifier: {
1893 if (getParser().parseIdentifier(Identifier))
1894 return ParseStatus::Failure;
1895
1896 unsigned Opcode;
1897 if (Identifier == "C0")
1898 Opcode = 0;
1899 else if (Identifier == "C1")
1900 Opcode = 1;
1901 else if (Identifier == "C2")
1902 Opcode = 2;
1903 else
1904 break;
1905
1906 Res = MCConstantExpr::create(Opcode, getContext());
1908 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1909 return ParseStatus::Success;
1910 }
1911 case AsmToken::Percent: {
1912 // Discard operand with modifier.
1913 break;
1914 }
1915 }
1916
1917 return generateImmOutOfRangeError(
1918 S, 0, 2,
1919 "opcode must be a valid opcode name or an immediate in the range");
1920}
1921
1922ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1923 SMLoc S = getLoc();
1924 const MCExpr *Res;
1925
1926 auto SysRegFromConstantInt = [this](const MCExpr *E, SMLoc S) {
1927 if (auto *CE = dyn_cast<MCConstantExpr>(E)) {
1928 int64_t Imm = CE->getValue();
1929 if (isUInt<12>(Imm)) {
1930 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1931 // Accept an immediate representing a named Sys Reg if it satisfies the
1932 // the required features.
1933 for (auto &Reg : Range) {
1934 if (Reg.IsAltName || Reg.IsDeprecatedName)
1935 continue;
1936 if (Reg.haveRequiredFeatures(STI->getFeatureBits()))
1937 return RISCVOperand::createSysReg(Reg.Name, S, Imm);
1938 }
1939 // Accept an immediate representing an un-named Sys Reg if the range is
1940 // valid, regardless of the required features.
1941 return RISCVOperand::createSysReg("", S, Imm);
1942 }
1943 }
1944 return std::unique_ptr<RISCVOperand>();
1945 };
1946
1947 switch (getLexer().getKind()) {
1948 default:
1949 return ParseStatus::NoMatch;
1950 case AsmToken::LParen:
1951 case AsmToken::Minus:
1952 case AsmToken::Plus:
1953 case AsmToken::Exclaim:
1954 case AsmToken::Tilde:
1955 case AsmToken::Integer:
1956 case AsmToken::String: {
1957 if (getParser().parseExpression(Res))
1958 return ParseStatus::Failure;
1959
1960 if (auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1961 Operands.push_back(std::move(SysOpnd));
1962 return ParseStatus::Success;
1963 }
1964
1965 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1966 }
1967 case AsmToken::Identifier: {
1969 if (getParser().parseIdentifier(Identifier))
1970 return ParseStatus::Failure;
1971
1972 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1973
1974 if (SysReg) {
1975 if (SysReg->IsDeprecatedName) {
1976 // Lookup the undeprecated name.
1977 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);
1978 for (auto &Reg : Range) {
1979 if (Reg.IsAltName || Reg.IsDeprecatedName)
1980 continue;
1981 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1982 Reg.Name + "'");
1983 }
1984 }
1985
1986 // Accept a named Sys Reg if the required features are present.
1987 const auto &FeatureBits = getSTI().getFeatureBits();
1988 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
1989 const auto *Feature = llvm::find_if(RISCVFeatureKV, [&](auto Feature) {
1990 return SysReg->FeaturesRequired[Feature.Value];
1991 });
1992 auto ErrorMsg = std::string("system register '") + SysReg->Name + "' ";
1993 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
1994 ErrorMsg += "is RV32 only";
1995 if (Feature != std::end(RISCVFeatureKV))
1996 ErrorMsg += " and ";
1997 }
1998 if (Feature != std::end(RISCVFeatureKV)) {
1999 ErrorMsg +=
2000 "requires '" + std::string(Feature->Key) + "' to be enabled";
2001 }
2002
2003 return Error(S, ErrorMsg);
2004 }
2005 Operands.push_back(
2006 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
2007 return ParseStatus::Success;
2008 }
2009
2010 // Accept a symbol name that evaluates to an absolute value.
2011 MCSymbol *Sym = getContext().lookupSymbol(Identifier);
2012 if (Sym && Sym->isVariable()) {
2013 // Pass false for SetUsed, since redefining the value later does not
2014 // affect this instruction.
2015 if (auto SysOpnd = SysRegFromConstantInt(
2016 Sym->getVariableValue(/*SetUsed=*/false), S)) {
2017 Operands.push_back(std::move(SysOpnd));
2018 return ParseStatus::Success;
2019 }
2020 }
2021
2022 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2023 "operand must be a valid system register "
2024 "name or an integer in the range");
2025 }
2026 case AsmToken::Percent: {
2027 // Discard operand with modifier.
2028 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2029 }
2030 }
2031
2032 return ParseStatus::NoMatch;
2033}
2034
2035ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
2036 SMLoc S = getLoc();
2037
2038 // Parse special floats (inf/nan/min) representation.
2039 if (getTok().is(AsmToken::Identifier)) {
2040 StringRef Identifier = getTok().getIdentifier();
2041 if (Identifier.compare_insensitive("inf") == 0) {
2042 Operands.push_back(
2043 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
2044 getTok().getEndLoc(), isRV64()));
2045 } else if (Identifier.compare_insensitive("nan") == 0) {
2046 Operands.push_back(
2047 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
2048 getTok().getEndLoc(), isRV64()));
2049 } else if (Identifier.compare_insensitive("min") == 0) {
2050 Operands.push_back(
2051 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
2052 getTok().getEndLoc(), isRV64()));
2053 } else {
2054 return TokError("invalid floating point literal");
2055 }
2056
2057 Lex(); // Eat the token.
2058
2059 return ParseStatus::Success;
2060 }
2061
2062 // Handle negation, as that still comes through as a separate token.
2063 bool IsNegative = parseOptionalToken(AsmToken::Minus);
2064
2065 const AsmToken &Tok = getTok();
2066 if (!Tok.is(AsmToken::Real))
2067 return TokError("invalid floating point immediate");
2068
2069 // Parse FP representation.
2070 APFloat RealVal(APFloat::IEEEdouble());
2071 auto StatusOrErr =
2072 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2073 if (errorToBool(StatusOrErr.takeError()))
2074 return TokError("invalid floating point representation");
2075
2076 if (IsNegative)
2077 RealVal.changeSign();
2078
2079 Operands.push_back(RISCVOperand::createFPImm(
2080 RealVal.bitcastToAPInt().getZExtValue(), S));
2081
2082 Lex(); // Eat the token.
2083
2084 return ParseStatus::Success;
2085}
2086
2087ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {
2088 SMLoc S = getLoc();
2089 SMLoc E;
2090 const MCExpr *Res;
2091
2092 switch (getLexer().getKind()) {
2093 default:
2094 return ParseStatus::NoMatch;
2095 case AsmToken::LParen:
2096 case AsmToken::Dot:
2097 case AsmToken::Minus:
2098 case AsmToken::Plus:
2099 case AsmToken::Exclaim:
2100 case AsmToken::Tilde:
2101 case AsmToken::Integer:
2102 case AsmToken::String:
2104 if (getParser().parseExpression(Res, E))
2105 return ParseStatus::Failure;
2106 break;
2107 case AsmToken::Percent:
2108 return parseOperandWithModifier(Operands);
2109 }
2110
2111 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2112 return ParseStatus::Success;
2113}
2114
2115ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
2116 SMLoc S = getLoc();
2117 SMLoc E;
2118
2119 if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
2120 return ParseStatus::Failure;
2121
2122 if (getLexer().getKind() != AsmToken::Identifier)
2123 return Error(getLoc(), "expected valid identifier for operand modifier");
2124 StringRef Identifier = getParser().getTok().getIdentifier();
2127 return Error(getLoc(), "unrecognized operand modifier");
2128
2129 getParser().Lex(); // Eat the identifier
2130 if (parseToken(AsmToken::LParen, "expected '('"))
2131 return ParseStatus::Failure;
2132
2133 const MCExpr *SubExpr;
2134 if (getParser().parseParenExpression(SubExpr, E))
2135 return ParseStatus::Failure;
2136
2137 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
2138 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
2139 return ParseStatus::Success;
2140}
2141
2142ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
2143 SMLoc S = getLoc();
2144 const MCExpr *Res;
2145
2146 if (getLexer().getKind() != AsmToken::Identifier)
2147 return ParseStatus::NoMatch;
2148
2150 AsmToken Tok = getLexer().getTok();
2151
2152 if (getParser().parseIdentifier(Identifier))
2153 return ParseStatus::Failure;
2154
2156
2157 if (Identifier.consume_back("@plt"))
2158 return Error(getLoc(), "'@plt' operand not valid for instruction");
2159
2160 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2161
2162 if (Sym->isVariable()) {
2163 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
2164 if (!isa<MCSymbolRefExpr>(V)) {
2165 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
2166 return ParseStatus::NoMatch;
2167 }
2168 Res = V;
2169 } else
2171
2172 MCBinaryExpr::Opcode Opcode;
2173 switch (getLexer().getKind()) {
2174 default:
2175 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2176 return ParseStatus::Success;
2177 case AsmToken::Plus:
2178 Opcode = MCBinaryExpr::Add;
2179 getLexer().Lex();
2180 break;
2181 case AsmToken::Minus:
2182 Opcode = MCBinaryExpr::Sub;
2183 getLexer().Lex();
2184 break;
2185 }
2186
2187 const MCExpr *Expr;
2188 if (getParser().parseExpression(Expr, E))
2189 return ParseStatus::Failure;
2190 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
2191 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2192 return ParseStatus::Success;
2193}
2194
2195ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2196 SMLoc S = getLoc();
2197 const MCExpr *Res;
2198
2199 if (getLexer().getKind() != AsmToken::Identifier)
2200 return ParseStatus::NoMatch;
2201
2202 // Avoid parsing the register in `call rd, foo` as a call symbol.
2203 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
2204 return ParseStatus::NoMatch;
2205
2207 if (getParser().parseIdentifier(Identifier))
2208 return ParseStatus::Failure;
2209
2211
2213 (void)Identifier.consume_back("@plt");
2214
2215 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2217 Res = RISCVMCExpr::create(Res, Kind, getContext());
2218 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2219 return ParseStatus::Success;
2220}
2221
2222ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2223 SMLoc S = getLoc();
2224 SMLoc E;
2225 const MCExpr *Res;
2226
2227 if (getParser().parseExpression(Res, E))
2228 return ParseStatus::Failure;
2229
2230 if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
2231 cast<MCSymbolRefExpr>(Res)->getKind() ==
2232 MCSymbolRefExpr::VariantKind::VK_PLT)
2233 return Error(S, "operand must be a valid jump target");
2234
2235 Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
2236 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2237 return ParseStatus::Success;
2238}
2239
2240ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2241 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2242 // both being acceptable forms. When parsing `jal ra, foo` this function
2243 // will be called for the `ra` register operand in an attempt to match the
2244 // single-operand alias. parseJALOffset must fail for this case. It would
2245 // seem logical to try parse the operand using parseImmediate and return
2246 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2247 // the second form rather than the first). We can't do this as there's no
2248 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2249 // is an identifier and is followed by a comma.
2250 if (getLexer().is(AsmToken::Identifier) &&
2251 getLexer().peekTok().is(AsmToken::Comma))
2252 return ParseStatus::NoMatch;
2253
2254 return parseImmediate(Operands);
2255}
2256
2257bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
2258 unsigned &Sew, unsigned &Lmul,
2259 bool &Fractional, bool &TailAgnostic,
2260 bool &MaskAgnostic) {
2261 if (Tok.isNot(AsmToken::Identifier))
2262 return true;
2263
2265
2266 switch (State) {
2267 case VTypeState_SEW:
2268 if (!Identifier.consume_front("e"))
2269 break;
2270 if (Identifier.getAsInteger(10, Sew))
2271 break;
2272 if (!RISCVVType::isValidSEW(Sew))
2273 break;
2274 State = VTypeState_LMUL;
2275 return false;
2276 case VTypeState_LMUL: {
2277 if (!Identifier.consume_front("m"))
2278 break;
2279 Fractional = Identifier.consume_front("f");
2280 if (Identifier.getAsInteger(10, Lmul))
2281 break;
2282 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2283 break;
2284
2285 if (Fractional) {
2286 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2287 unsigned MinLMUL = ELEN / 8;
2288 if (Lmul > MinLMUL)
2289 Warning(Tok.getLoc(),
2290 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2291 Twine(MinLMUL) + " is reserved");
2292 }
2293
2294 State = VTypeState_TailPolicy;
2295 return false;
2296 }
2297 case VTypeState_TailPolicy:
2298 if (Identifier == "ta")
2299 TailAgnostic = true;
2300 else if (Identifier == "tu")
2301 TailAgnostic = false;
2302 else
2303 break;
2304 State = VTypeState_MaskPolicy;
2305 return false;
2306 case VTypeState_MaskPolicy:
2307 if (Identifier == "ma")
2308 MaskAgnostic = true;
2309 else if (Identifier == "mu")
2310 MaskAgnostic = false;
2311 else
2312 break;
2313 State = VTypeState_Done;
2314 return false;
2315 case VTypeState_Done:
2316 // Extra token?
2317 break;
2318 }
2319
2320 return true;
2321}
2322
2323ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2324 SMLoc S = getLoc();
2325
2326 unsigned Sew = 0;
2327 unsigned Lmul = 0;
2328 bool Fractional = false;
2329 bool TailAgnostic = false;
2330 bool MaskAgnostic = false;
2331
2332 VTypeState State = VTypeState_SEW;
2333 SMLoc SEWLoc = S;
2334
2335 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2336 MaskAgnostic))
2337 return ParseStatus::NoMatch;
2338
2339 getLexer().Lex();
2340
2341 while (parseOptionalToken(AsmToken::Comma)) {
2342 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2343 MaskAgnostic))
2344 break;
2345
2346 getLexer().Lex();
2347 }
2348
2349 if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {
2350 RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2351 if (Fractional) {
2352 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2353 unsigned MaxSEW = ELEN / Lmul;
2354 // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2355 if (MaxSEW >= 8 && Sew > MaxSEW)
2356 Warning(SEWLoc,
2357 "use of vtype encodings with SEW > " + Twine(MaxSEW) +
2358 " and LMUL == mf" + Twine(Lmul) +
2359 " may not be compatible with all RVV implementations");
2360 }
2361
2362 unsigned VTypeI =
2363 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
2364 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2365 return ParseStatus::Success;
2366 }
2367
2368 return generateVTypeError(S);
2369}
2370
2371bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2372 return Error(
2373 ErrorLoc,
2374 "operand must be "
2375 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2376}
2377
2378ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2379 if (getLexer().isNot(AsmToken::Identifier))
2380 return ParseStatus::NoMatch;
2381
2382 StringRef Name = getLexer().getTok().getIdentifier();
2383 if (!Name.consume_back(".t"))
2384 return Error(getLoc(), "expected '.t' suffix");
2386
2387 if (!Reg)
2388 return ParseStatus::NoMatch;
2389 if (Reg != RISCV::V0)
2390 return ParseStatus::NoMatch;
2391 SMLoc S = getLoc();
2393 getLexer().Lex();
2394 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2395 return ParseStatus::Success;
2396}
2397
2398ParseStatus RISCVAsmParser::parseGPRAsFPR64(OperandVector &Operands) {
2399 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2400 return ParseStatus::NoMatch;
2401
2402 return parseGPRAsFPR(Operands);
2403}
2404
2405ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2406 if (getLexer().isNot(AsmToken::Identifier))
2407 return ParseStatus::NoMatch;
2408
2409 StringRef Name = getLexer().getTok().getIdentifier();
2411
2412 if (!Reg)
2413 return ParseStatus::NoMatch;
2414 SMLoc S = getLoc();
2416 getLexer().Lex();
2417 Operands.push_back(RISCVOperand::createReg(
2418 Reg, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2419 return ParseStatus::Success;
2420}
2421
2422ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
2423 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2424 return ParseStatus::NoMatch;
2425
2426 if (getLexer().isNot(AsmToken::Identifier))
2427 return ParseStatus::NoMatch;
2428
2429 StringRef Name = getLexer().getTok().getIdentifier();
2431
2432 if (!Reg)
2433 return ParseStatus::NoMatch;
2434
2435 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2436 return ParseStatus::NoMatch;
2437
2438 if ((Reg - RISCV::X0) & 1) {
2439 // Only report the even register error if we have at least Zfinx so we know
2440 // some FP is enabled. We already checked F earlier.
2441 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2442 return TokError("double precision floating point operands must use even "
2443 "numbered X register");
2444 return ParseStatus::NoMatch;
2445 }
2446
2447 SMLoc S = getLoc();
2449 getLexer().Lex();
2450
2451 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2453 Reg, RISCV::sub_gpr_even,
2454 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2455 Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));
2456 return ParseStatus::Success;
2457}
2458
2459template <bool IsRV64>
2460ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2461 return parseGPRPair(Operands, IsRV64);
2462}
2463
2464ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2465 bool IsRV64Inst) {
2466 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2467 // RV64 as it will prevent matching the RV64 version of the same instruction
2468 // that doesn't use a GPRPair.
2469 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2470 // still parse as a pair.
2471 if (!IsRV64Inst && isRV64())
2472 return ParseStatus::NoMatch;
2473
2474 if (getLexer().isNot(AsmToken::Identifier))
2475 return ParseStatus::NoMatch;
2476
2477 StringRef Name = getLexer().getTok().getIdentifier();
2479
2480 if (!Reg)
2481 return ParseStatus::NoMatch;
2482
2483 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg))
2484 return ParseStatus::NoMatch;
2485
2486 if ((Reg - RISCV::X0) & 1)
2487 return TokError("register must be even");
2488
2489 SMLoc S = getLoc();
2491 getLexer().Lex();
2492
2493 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2495 Reg, RISCV::sub_gpr_even,
2496 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2497 Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2498 return ParseStatus::Success;
2499}
2500
2501ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2502 if (getLexer().isNot(AsmToken::Identifier))
2503 return TokError(
2504 "operand must be a valid floating point rounding mode mnemonic");
2505
2506 StringRef Str = getLexer().getTok().getIdentifier();
2508
2509 if (FRM == RISCVFPRndMode::Invalid)
2510 return TokError(
2511 "operand must be a valid floating point rounding mode mnemonic");
2512
2513 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2514 Lex(); // Eat identifier token.
2515 return ParseStatus::Success;
2516}
2517
2518ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2519 const AsmToken &Tok = getLexer().getTok();
2520
2521 if (Tok.is(AsmToken::Integer)) {
2522 if (Tok.getIntVal() != 0)
2523 goto ParseFail;
2524
2525 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2526 Lex();
2527 return ParseStatus::Success;
2528 }
2529
2530 if (Tok.is(AsmToken::Identifier)) {
2531 StringRef Str = Tok.getIdentifier();
2532
2533 // Letters must be unique, taken from 'iorw', and in ascending order. This
2534 // holds as long as each individual character is one of 'iorw' and is
2535 // greater than the previous character.
2536 unsigned Imm = 0;
2537 bool Valid = true;
2538 char Prev = '\0';
2539 for (char c : Str) {
2540 switch (c) {
2541 default:
2542 Valid = false;
2543 break;
2544 case 'i':
2546 break;
2547 case 'o':
2549 break;
2550 case 'r':
2552 break;
2553 case 'w':
2555 break;
2556 }
2557
2558 if (c <= Prev) {
2559 Valid = false;
2560 break;
2561 }
2562 Prev = c;
2563 }
2564
2565 if (!Valid)
2566 goto ParseFail;
2567
2568 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2569 Lex();
2570 return ParseStatus::Success;
2571 }
2572
2573ParseFail:
2574 return TokError("operand must be formed of letters selected in-order from "
2575 "'iorw' or be 0");
2576}
2577
2578ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2579 if (parseToken(AsmToken::LParen, "expected '('"))
2580 return ParseStatus::Failure;
2581 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2582
2583 if (!parseRegister(Operands).isSuccess())
2584 return Error(getLoc(), "expected register");
2585
2586 if (parseToken(AsmToken::RParen, "expected ')'"))
2587 return ParseStatus::Failure;
2588 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2589
2590 return ParseStatus::Success;
2591}
2592
2593ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2594 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2595 // as one of their register operands, such as `(a0)`. This just denotes that
2596 // the register (in this case `a0`) contains a memory address.
2597 //
2598 // Normally, we would be able to parse these by putting the parens into the
2599 // instruction string. However, GNU as also accepts a zero-offset memory
2600 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2601 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2602 // do not accept an immediate operand, and we do not want to add a "dummy"
2603 // operand that is silently dropped.
2604 //
2605 // Instead, we use this custom parser. This will: allow (and discard) an
2606 // offset if it is zero; require (and discard) parentheses; and add only the
2607 // parsed register operand to `Operands`.
2608 //
2609 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2610 // which will only print the register surrounded by parentheses (which GNU as
2611 // also uses as its canonical representation for these operands).
2612 std::unique_ptr<RISCVOperand> OptionalImmOp;
2613
2614 if (getLexer().isNot(AsmToken::LParen)) {
2615 // Parse an Integer token. We do not accept arbritrary constant expressions
2616 // in the offset field (because they may include parens, which complicates
2617 // parsing a lot).
2618 int64_t ImmVal;
2619 SMLoc ImmStart = getLoc();
2620 if (getParser().parseIntToken(ImmVal,
2621 "expected '(' or optional integer offset"))
2622 return ParseStatus::Failure;
2623
2624 // Create a RISCVOperand for checking later (so the error messages are
2625 // nicer), but we don't add it to Operands.
2626 SMLoc ImmEnd = getLoc();
2627 OptionalImmOp =
2628 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
2629 ImmStart, ImmEnd, isRV64());
2630 }
2631
2632 if (parseToken(AsmToken::LParen,
2633 OptionalImmOp ? "expected '(' after optional integer offset"
2634 : "expected '(' or optional integer offset"))
2635 return ParseStatus::Failure;
2636
2637 if (!parseRegister(Operands).isSuccess())
2638 return Error(getLoc(), "expected register");
2639
2640 if (parseToken(AsmToken::RParen, "expected ')'"))
2641 return ParseStatus::Failure;
2642
2643 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2644 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2645 return Error(
2646 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2647 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2648
2649 return ParseStatus::Success;
2650}
2651
2652ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2653 // RR : a2(a1)
2654 if (getLexer().getKind() != AsmToken::Identifier)
2655 return ParseStatus::NoMatch;
2656
2657 StringRef RegName = getLexer().getTok().getIdentifier();
2659 if (!Reg)
2660 return Error(getLoc(), "invalid register");
2661 getLexer().Lex();
2662
2663 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
2664 return ParseStatus::Failure;
2665
2666 if (getLexer().getKind() != AsmToken::Identifier)
2667 return Error(getLoc(), "expected register");
2668
2669 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2670 MCRegister Reg2 = matchRegisterNameHelper(Reg2Name);
2671 if (!Reg2)
2672 return Error(getLoc(), "invalid register");
2673 getLexer().Lex();
2674
2675 if (parseToken(AsmToken::RParen, "expected ')'"))
2676 return ParseStatus::Failure;
2677
2678 Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));
2679
2680 return ParseStatus::Success;
2681}
2682
2683ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
2684 // Rlist: {ra [, s0[-sN]]}
2685 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2686 SMLoc S = getLoc();
2687
2688 if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
2689 return ParseStatus::Failure;
2690
2691 bool IsEABI = isRVE();
2692
2693 if (getLexer().isNot(AsmToken::Identifier))
2694 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2695
2696 StringRef RegName = getLexer().getTok().getIdentifier();
2698 MCRegister RegEnd;
2699 if (RegStart != RISCV::X1)
2700 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2701 getLexer().Lex();
2702
2703 // parse case like ,s0
2704 if (parseOptionalToken(AsmToken::Comma)) {
2705 if (getLexer().isNot(AsmToken::Identifier))
2706 return Error(getLoc(), "invalid register");
2707 StringRef RegName = getLexer().getTok().getIdentifier();
2708 RegStart = matchRegisterNameHelper(RegName);
2709 if (!RegStart)
2710 return Error(getLoc(), "invalid register");
2711 if (RegStart != RISCV::X8)
2712 return Error(getLoc(),
2713 "continuous register list must start from 's0' or 'x8'");
2714 getLexer().Lex(); // eat reg
2715 }
2716
2717 // parse case like -s1
2718 if (parseOptionalToken(AsmToken::Minus)) {
2719 StringRef EndName = getLexer().getTok().getIdentifier();
2720 // FIXME: the register mapping and checks of EABI is wrong
2721 RegEnd = matchRegisterNameHelper(EndName);
2722 if (!RegEnd)
2723 return Error(getLoc(), "invalid register");
2724 if (IsEABI && RegEnd != RISCV::X9)
2725 return Error(getLoc(), "contiguous register list of EABI can only be "
2726 "'s0-s1' or 'x8-x9' pair");
2727 getLexer().Lex();
2728 }
2729
2730 if (!IsEABI) {
2731 // parse extra part like ', x18[-x20]' for XRegList
2732 if (parseOptionalToken(AsmToken::Comma)) {
2733 if (RegEnd != RISCV::X9)
2734 return Error(
2735 getLoc(),
2736 "first contiguous registers pair of register list must be 'x8-x9'");
2737
2738 // parse ', x18' for extra part
2739 if (getLexer().isNot(AsmToken::Identifier))
2740 return Error(getLoc(), "invalid register");
2741 StringRef EndName = getLexer().getTok().getIdentifier();
2742 if (MatchRegisterName(EndName) != RISCV::X18)
2743 return Error(getLoc(),
2744 "second contiguous registers pair of register list "
2745 "must start from 'x18'");
2746 getLexer().Lex();
2747
2748 // parse '-x20' for extra part
2749 if (parseOptionalToken(AsmToken::Minus)) {
2750 if (getLexer().isNot(AsmToken::Identifier))
2751 return Error(getLoc(), "invalid register");
2752 EndName = getLexer().getTok().getIdentifier();
2753 if (!MatchRegisterName(EndName))
2754 return Error(getLoc(), "invalid register");
2755 getLexer().Lex();
2756 }
2757 RegEnd = MatchRegisterName(EndName);
2758 }
2759 }
2760
2761 if (RegEnd == RISCV::X26)
2762 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2763 "x18-x26} is not supported");
2764
2765 if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
2766 return ParseStatus::Failure;
2767
2768 if (!RegEnd)
2769 RegEnd = RegStart;
2770
2771 auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
2772 if (Encode == RISCVZC::INVALID_RLIST)
2773 return Error(S, "invalid register list");
2774 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2775
2776 return ParseStatus::Success;
2777}
2778
2779ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2780 bool ExpectNegative) {
2781 bool Negative = parseOptionalToken(AsmToken::Minus);
2782
2783 SMLoc S = getLoc();
2784 int64_t StackAdjustment = getLexer().getTok().getIntVal();
2785 unsigned Spimm = 0;
2786 unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
2787
2788 if (Negative != ExpectNegative ||
2789 !RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64()))
2790 return ParseStatus::NoMatch;
2791 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2792 getLexer().Lex();
2793 return ParseStatus::Success;
2794}
2795
2796/// Looks at a token type and creates the relevant operand from this
2797/// information, adding to Operands. If operand was parsed, returns false, else
2798/// true.
2799bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2800 // Check if the current operand has a custom associated parser, if so, try to
2801 // custom parse the operand, or fallback to the general approach.
2803 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
2804 if (Result.isSuccess())
2805 return false;
2806 if (Result.isFailure())
2807 return true;
2808
2809 // Attempt to parse token as a register.
2810 if (parseRegister(Operands, true).isSuccess())
2811 return false;
2812
2813 // Attempt to parse token as an immediate
2814 if (parseImmediate(Operands).isSuccess()) {
2815 // Parse memory base register if present
2816 if (getLexer().is(AsmToken::LParen))
2817 return !parseMemOpBaseReg(Operands).isSuccess();
2818 return false;
2819 }
2820
2821 // Finally we have exhausted all options and must declare defeat.
2822 Error(getLoc(), "unknown operand");
2823 return true;
2824}
2825
2826bool RISCVAsmParser::parseInstruction(ParseInstructionInfo &Info,
2827 StringRef Name, SMLoc NameLoc,
2829 // Ensure that if the instruction occurs when relaxation is enabled,
2830 // relocations are forced for the file. Ideally this would be done when there
2831 // is enough information to reliably determine if the instruction itself may
2832 // cause relaxations. Unfortunately instruction processing stage occurs in the
2833 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2834 // for the entire file.
2835 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2836 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2837 if (Assembler != nullptr) {
2838 RISCVAsmBackend &MAB =
2839 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
2840 MAB.setForceRelocs();
2841 }
2842 }
2843
2844 // First operand is token for instruction
2845 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
2846
2847 // If there are no more operands, then finish
2848 if (getLexer().is(AsmToken::EndOfStatement)) {
2849 getParser().Lex(); // Consume the EndOfStatement.
2850 return false;
2851 }
2852
2853 // Parse first operand
2854 if (parseOperand(Operands, Name))
2855 return true;
2856
2857 // Parse until end of statement, consuming commas between operands
2858 while (parseOptionalToken(AsmToken::Comma)) {
2859 // Parse next operand
2860 if (parseOperand(Operands, Name))
2861 return true;
2862 }
2863
2864 if (getParser().parseEOL("unexpected token")) {
2865 getParser().eatToEndOfStatement();
2866 return true;
2867 }
2868 return false;
2869}
2870
2871bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2874
2875 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2876 Kind = RE->getKind();
2877 Expr = RE->getSubExpr();
2878 }
2879
2880 MCValue Res;
2881 MCFixup Fixup;
2882 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2883 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
2884 return false;
2885}
2886
2887bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
2888 MCValue Res;
2889 MCFixup Fixup;
2890 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
2891 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
2892 Res.getSymB();
2893 }
2894 return false;
2895}
2896
2897ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
2898 StringRef IDVal = DirectiveID.getString();
2899
2900 if (IDVal == ".option")
2901 return parseDirectiveOption();
2902 if (IDVal == ".attribute")
2903 return parseDirectiveAttribute();
2904 if (IDVal == ".insn")
2905 return parseDirectiveInsn(DirectiveID.getLoc());
2906 if (IDVal == ".variant_cc")
2907 return parseDirectiveVariantCC();
2908
2909 return ParseStatus::NoMatch;
2910}
2911
2912bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
2913 bool FromOptionDirective) {
2914 for (auto &Feature : RISCVFeatureKV)
2916 clearFeatureBits(Feature.Value, Feature.Key);
2917
2919 Arch, /*EnableExperimentalExtension=*/true,
2920 /*ExperimentalExtensionVersionCheck=*/true);
2921 if (!ParseResult) {
2922 std::string Buffer;
2923 raw_string_ostream OutputErrMsg(Buffer);
2924 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2925 OutputErrMsg << "invalid arch name '" << Arch << "', "
2926 << ErrMsg.getMessage();
2927 });
2928
2929 return Error(Loc, OutputErrMsg.str());
2930 }
2931 auto &ISAInfo = *ParseResult;
2932
2933 for (auto &Feature : RISCVFeatureKV)
2934 if (ISAInfo->hasExtension(Feature.Key))
2935 setFeatureBits(Feature.Value, Feature.Key);
2936
2937 if (FromOptionDirective) {
2938 if (ISAInfo->getXLen() == 32 && isRV64())
2939 return Error(Loc, "bad arch string switching from rv64 to rv32");
2940 else if (ISAInfo->getXLen() == 64 && !isRV64())
2941 return Error(Loc, "bad arch string switching from rv32 to rv64");
2942 }
2943
2944 if (ISAInfo->getXLen() == 32)
2945 clearFeatureBits(RISCV::Feature64Bit, "64bit");
2946 else if (ISAInfo->getXLen() == 64)
2947 setFeatureBits(RISCV::Feature64Bit, "64bit");
2948 else
2949 return Error(Loc, "bad arch string " + Arch);
2950
2951 Result = ISAInfo->toString();
2952 return false;
2953}
2954
2955bool RISCVAsmParser::parseDirectiveOption() {
2956 MCAsmParser &Parser = getParser();
2957 // Get the option token.
2958 AsmToken Tok = Parser.getTok();
2959
2960 // At the moment only identifiers are supported.
2961 if (parseToken(AsmToken::Identifier, "expected identifier"))
2962 return true;
2963
2965
2966 if (Option == "push") {
2967 if (Parser.parseEOL())
2968 return true;
2969
2970 getTargetStreamer().emitDirectiveOptionPush();
2971 pushFeatureBits();
2972 return false;
2973 }
2974
2975 if (Option == "pop") {
2976 SMLoc StartLoc = Parser.getTok().getLoc();
2977 if (Parser.parseEOL())
2978 return true;
2979
2980 getTargetStreamer().emitDirectiveOptionPop();
2981 if (popFeatureBits())
2982 return Error(StartLoc, ".option pop with no .option push");
2983
2984 return false;
2985 }
2986
2987 if (Option == "arch") {
2989 do {
2990 if (Parser.parseComma())
2991 return true;
2992
2994 if (parseOptionalToken(AsmToken::Plus))
2995 Type = RISCVOptionArchArgType::Plus;
2996 else if (parseOptionalToken(AsmToken::Minus))
2997 Type = RISCVOptionArchArgType::Minus;
2998 else if (!Args.empty())
2999 return Error(Parser.getTok().getLoc(),
3000 "unexpected token, expected + or -");
3001 else
3002 Type = RISCVOptionArchArgType::Full;
3003
3004 if (Parser.getTok().isNot(AsmToken::Identifier))
3005 return Error(Parser.getTok().getLoc(),
3006 "unexpected token, expected identifier");
3007
3008 StringRef Arch = Parser.getTok().getString();
3009 SMLoc Loc = Parser.getTok().getLoc();
3010 Parser.Lex();
3011
3012 if (Type == RISCVOptionArchArgType::Full) {
3013 std::string Result;
3014 if (resetToArch(Arch, Loc, Result, true))
3015 return true;
3016
3017 Args.emplace_back(Type, Result);
3018 break;
3019 }
3020
3021 if (isDigit(Arch.back()))
3022 return Error(
3023 Loc, "extension version number parsing not currently implemented");
3024
3025 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
3026 if (!enableExperimentalExtension() &&
3027 StringRef(Feature).starts_with("experimental-"))
3028 return Error(Loc, "unexpected experimental extensions");
3029 auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);
3030 if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)
3031 return Error(Loc, "unknown extension feature");
3032
3033 Args.emplace_back(Type, Arch.str());
3034
3035 if (Type == RISCVOptionArchArgType::Plus) {
3036 FeatureBitset OldFeatureBits = STI->getFeatureBits();
3037
3038 setFeatureBits(Ext->Value, Ext->Key);
3040 if (!ParseResult) {
3041 copySTI().setFeatureBits(OldFeatureBits);
3042 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3043
3044 std::string Buffer;
3045 raw_string_ostream OutputErrMsg(Buffer);
3046 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
3047 OutputErrMsg << ErrMsg.getMessage();
3048 });
3049
3050 return Error(Loc, OutputErrMsg.str());
3051 }
3052 } else {
3053 assert(Type == RISCVOptionArchArgType::Minus);
3054 // It is invalid to disable an extension that there are other enabled
3055 // extensions depend on it.
3056 // TODO: Make use of RISCVISAInfo to handle this
3057 for (auto &Feature : RISCVFeatureKV) {
3058 if (getSTI().hasFeature(Feature.Value) &&
3059 Feature.Implies.test(Ext->Value))
3060 return Error(Loc, Twine("can't disable ") + Ext->Key +
3061 " extension; " + Feature.Key +
3062 " extension requires " + Ext->Key +
3063 " extension");
3064 }
3065
3066 clearFeatureBits(Ext->Value, Ext->Key);
3067 }
3068 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
3069
3070 if (Parser.parseEOL())
3071 return true;
3072
3073 getTargetStreamer().emitDirectiveOptionArch(Args);
3074 return false;
3075 }
3076
3077 if (Option == "rvc") {
3078 if (Parser.parseEOL())
3079 return true;
3080
3081 getTargetStreamer().emitDirectiveOptionRVC();
3082 setFeatureBits(RISCV::FeatureStdExtC, "c");
3083 return false;
3084 }
3085
3086 if (Option == "norvc") {
3087 if (Parser.parseEOL())
3088 return true;
3089
3090 getTargetStreamer().emitDirectiveOptionNoRVC();
3091 clearFeatureBits(RISCV::FeatureStdExtC, "c");
3092 clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
3093 return false;
3094 }
3095
3096 if (Option == "pic") {
3097 if (Parser.parseEOL())
3098 return true;
3099
3100 getTargetStreamer().emitDirectiveOptionPIC();
3101 ParserOptions.IsPicEnabled = true;
3102 return false;
3103 }
3104
3105 if (Option == "nopic") {
3106 if (Parser.parseEOL())
3107 return true;
3108
3109 getTargetStreamer().emitDirectiveOptionNoPIC();
3110 ParserOptions.IsPicEnabled = false;
3111 return false;
3112 }
3113
3114 if (Option == "relax") {
3115 if (Parser.parseEOL())
3116 return true;
3117
3118 getTargetStreamer().emitDirectiveOptionRelax();
3119 setFeatureBits(RISCV::FeatureRelax, "relax");
3120 return false;
3121 }
3122
3123 if (Option == "norelax") {
3124 if (Parser.parseEOL())
3125 return true;
3126
3127 getTargetStreamer().emitDirectiveOptionNoRelax();
3128 clearFeatureBits(RISCV::FeatureRelax, "relax");
3129 return false;
3130 }
3131
3132 // Unknown option.
3133 Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
3134 "'rvc', 'norvc', 'arch', 'relax' or "
3135 "'norelax'");
3136 Parser.eatToEndOfStatement();
3137 return false;
3138}
3139
3140/// parseDirectiveAttribute
3141/// ::= .attribute expression ',' ( expression | "string" )
3142/// ::= .attribute identifier ',' ( expression | "string" )
3143bool RISCVAsmParser::parseDirectiveAttribute() {
3144 MCAsmParser &Parser = getParser();
3145 int64_t Tag;
3146 SMLoc TagLoc;
3147 TagLoc = Parser.getTok().getLoc();
3148 if (Parser.getTok().is(AsmToken::Identifier)) {
3149 StringRef Name = Parser.getTok().getIdentifier();
3150 std::optional<unsigned> Ret =
3152 if (!Ret)
3153 return Error(TagLoc, "attribute name not recognised: " + Name);
3154 Tag = *Ret;
3155 Parser.Lex();
3156 } else {
3157 const MCExpr *AttrExpr;
3158
3159 TagLoc = Parser.getTok().getLoc();
3160 if (Parser.parseExpression(AttrExpr))
3161 return true;
3162
3163 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
3164 if (check(!CE, TagLoc, "expected numeric constant"))
3165 return true;
3166
3167 Tag = CE->getValue();
3168 }
3169
3170 if (Parser.parseComma())
3171 return true;
3172
3173 StringRef StringValue;
3174 int64_t IntegerValue = 0;
3175 bool IsIntegerValue = true;
3176
3177 // RISC-V attributes have a string value if the tag number is odd
3178 // and an integer value if the tag number is even.
3179 if (Tag % 2)
3180 IsIntegerValue = false;
3181
3182 SMLoc ValueExprLoc = Parser.getTok().getLoc();
3183 if (IsIntegerValue) {
3184 const MCExpr *ValueExpr;
3185 if (Parser.parseExpression(ValueExpr))
3186 return true;
3187
3188 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
3189 if (!CE)
3190 return Error(ValueExprLoc, "expected numeric constant");
3191 IntegerValue = CE->getValue();
3192 } else {
3193 if (Parser.getTok().isNot(AsmToken::String))
3194 return Error(Parser.getTok().getLoc(), "expected string constant");
3195
3196 StringValue = Parser.getTok().getStringContents();
3197 Parser.Lex();
3198 }
3199
3200 if (Parser.parseEOL())
3201 return true;
3202
3203 if (IsIntegerValue)
3204 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3205 else if (Tag != RISCVAttrs::ARCH)
3206 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3207 else {
3208 std::string Result;
3209 if (resetToArch(StringValue, ValueExprLoc, Result, false))
3210 return true;
3211
3212 // Then emit the arch string.
3213 getTargetStreamer().emitTextAttribute(Tag, Result);
3214 }
3215
3216 return false;
3217}
3218
3219bool isValidInsnFormat(StringRef Format, bool AllowC) {
3220 return StringSwitch<bool>(Format)
3221 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
3222 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
3223 .Default(false);
3224}
3225
3226/// parseDirectiveInsn
3227/// ::= .insn [ format encoding, (operands (, operands)*) ]
3228/// ::= .insn [ length, value ]
3229/// ::= .insn [ value ]
3230bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3231 MCAsmParser &Parser = getParser();
3232
3233 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3234 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3235
3236 // Expect instruction format as identifier.
3238 SMLoc ErrorLoc = Parser.getTok().getLoc();
3239 if (Parser.parseIdentifier(Format)) {
3240 // Try parsing .insn [ length , ] value
3241 std::optional<int64_t> Length;
3242 int64_t Value = 0;
3243 if (Parser.parseAbsoluteExpression(Value))
3244 return true;
3245 if (Parser.parseOptionalToken(AsmToken::Comma)) {
3246 Length = Value;
3247 if (Parser.parseAbsoluteExpression(Value))
3248 return true;
3249
3250 if (*Length == 0 || (*Length % 2) != 0)
3251 return Error(ErrorLoc,
3252 "instruction lengths must be a non-zero multiple of two");
3253
3254 // TODO: Support Instructions > 64 bits.
3255 if (*Length > 8)
3256 return Error(ErrorLoc,
3257 "instruction lengths over 64 bits are not supported");
3258 }
3259
3260 // We only derive a length from the encoding for 16- and 32-bit
3261 // instructions, as the encodings for longer instructions are not frozen in
3262 // the spec.
3263 int64_t EncodingDerivedLength = ((Value & 0b11) == 0b11) ? 4 : 2;
3264
3265 if (Length) {
3266 // Only check the length against the encoding if the length is present and
3267 // could match
3268 if ((*Length <= 4) && (*Length != EncodingDerivedLength))
3269 return Error(ErrorLoc,
3270 "instruction length does not match the encoding");
3271
3272 if (!isUIntN(*Length * 8, Value))
3273 return Error(ErrorLoc, "encoding value does not fit into instruction");
3274 } else {
3275 if (!isUIntN(EncodingDerivedLength * 8, Value))
3276 return Error(ErrorLoc, "encoding value does not fit into instruction");
3277 }
3278
3279 if (!AllowC && (EncodingDerivedLength == 2))
3280 return Error(ErrorLoc, "compressed instructions are not allowed");
3281
3282 if (getParser().parseEOL("invalid operand for instruction")) {
3283 getParser().eatToEndOfStatement();
3284 return true;
3285 }
3286
3287 unsigned Opcode;
3288 if (Length) {
3289 switch (*Length) {
3290 case 2:
3291 Opcode = RISCV::Insn16;
3292 break;
3293 case 4:
3294 Opcode = RISCV::Insn32;
3295 break;
3296 case 6:
3297 Opcode = RISCV::Insn48;
3298 break;
3299 case 8:
3300 Opcode = RISCV::Insn64;
3301 break;
3302 default:
3303 llvm_unreachable("Error should have already been emitted");
3304 }
3305 } else
3306 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3307
3308 emitToStreamer(getStreamer(), MCInstBuilder(Opcode).addImm(Value));
3309 return false;
3310 }
3311
3312 if (!isValidInsnFormat(Format, AllowC))
3313 return Error(ErrorLoc, "invalid instruction format");
3314
3315 std::string FormatName = (".insn_" + Format).str();
3316
3319
3320 if (parseInstruction(Info, FormatName, L, Operands))
3321 return true;
3322
3323 unsigned Opcode;
3325 return matchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3326 ErrorInfo,
3327 /*MatchingInlineAsm=*/false);
3328}
3329
3330/// parseDirectiveVariantCC
3331/// ::= .variant_cc symbol
3332bool RISCVAsmParser::parseDirectiveVariantCC() {
3334 if (getParser().parseIdentifier(Name))
3335 return TokError("expected symbol name");
3336 if (parseEOL())
3337 return true;
3338 getTargetStreamer().emitDirectiveVariantCC(
3339 *getContext().getOrCreateSymbol(Name));
3340 return false;
3341}
3342
3343void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3344 MCInst CInst;
3345 bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
3346 if (Res)
3347 ++RISCVNumInstrsCompressed;
3348 S.emitInstruction((Res ? CInst : Inst), getSTI());
3349}
3350
3351void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3352 MCStreamer &Out) {
3354 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
3355
3356 for (MCInst &Inst : Seq) {
3357 emitToStreamer(Out, Inst);
3358 }
3359}
3360
3361void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
3362 const MCExpr *Symbol,
3364 unsigned SecondOpcode, SMLoc IDLoc,
3365 MCStreamer &Out) {
3366 // A pair of instructions for PC-relative addressing; expands to
3367 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3368 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3369 MCContext &Ctx = getContext();
3370
3371 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3372 Out.emitLabel(TmpLabel);
3373
3374 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
3375 emitToStreamer(
3376 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
3377
3378 const MCExpr *RefToLinkTmpLabel =
3381
3382 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3383 .addOperand(DestReg)
3384 .addOperand(TmpReg)
3385 .addExpr(RefToLinkTmpLabel));
3386}
3387
3388void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3389 MCStreamer &Out) {
3390 // The load local address pseudo-instruction "lla" is used in PC-relative
3391 // addressing of local symbols:
3392 // lla rdest, symbol
3393 // expands to
3394 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3395 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3396 MCOperand DestReg = Inst.getOperand(0);
3397 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3398 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3399 RISCV::ADDI, IDLoc, Out);
3400}
3401
3402void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3403 MCStreamer &Out) {
3404 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3405 // addressing of global symbols:
3406 // lga rdest, symbol
3407 // expands to
3408 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3409 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3410 MCOperand DestReg = Inst.getOperand(0);
3411 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3412 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3413 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
3414 SecondOpcode, IDLoc, Out);
3415}
3416
3417void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3418 MCStreamer &Out) {
3419 // The load address pseudo-instruction "la" is used in PC-relative and
3420 // GOT-indirect addressing of global symbols:
3421 // la rdest, symbol
3422 // is an alias for either (for non-PIC)
3423 // lla rdest, symbol
3424 // or (for PIC)
3425 // lga rdest, symbol
3426 if (ParserOptions.IsPicEnabled)
3427 emitLoadGlobalAddress(Inst, IDLoc, Out);
3428 else
3429 emitLoadLocalAddress(Inst, IDLoc, Out);
3430}
3431
3432void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3433 MCStreamer &Out) {
3434 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3435 // initial-exec TLS model addressing of global symbols:
3436 // la.tls.ie rdest, symbol
3437 // expands to
3438 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3439 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3440 MCOperand DestReg = Inst.getOperand(0);
3441 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3442 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3443 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
3444 SecondOpcode, IDLoc, Out);
3445}
3446
3447void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3448 MCStreamer &Out) {
3449 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3450 // global-dynamic TLS model addressing of global symbols:
3451 // la.tls.gd rdest, symbol
3452 // expands to
3453 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3454 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3455 MCOperand DestReg = Inst.getOperand(0);
3456 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3457 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
3458 RISCV::ADDI, IDLoc, Out);
3459}
3460
3461void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3462 SMLoc IDLoc, MCStreamer &Out,
3463 bool HasTmpReg) {
3464 // The load/store pseudo-instruction does a pc-relative load with
3465 // a symbol.
3466 //
3467 // The expansion looks like this
3468 //
3469 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3470 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3471 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3472 MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
3473 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3474 MCOperand TmpReg = Inst.getOperand(0);
3475 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3476 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3477 Opcode, IDLoc, Out);
3478}
3479
3480void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3481 int64_t Width, SMLoc IDLoc,
3482 MCStreamer &Out) {
3483 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3484 // amounts dependent on the XLEN.
3485 //
3486 // The expansion looks like this
3487 //
3488 // SLLI rd, rs, XLEN - Width
3489 // SR[A|R]I rd, rd, XLEN - Width
3490 MCOperand DestReg = Inst.getOperand(0);
3491 MCOperand SourceReg = Inst.getOperand(1);
3492
3493 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3494 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3495
3496 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3497
3498 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3499 .addOperand(DestReg)
3500 .addOperand(SourceReg)
3501 .addImm(ShAmt));
3502
3503 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3504 .addOperand(DestReg)
3505 .addOperand(DestReg)
3506 .addImm(ShAmt));
3507}
3508
3509void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3510 MCStreamer &Out) {
3511 if (Inst.getNumOperands() == 3) {
3512 // unmasked va >= x
3513 //
3514 // pseudoinstruction: vmsge{u}.vx vd, va, x
3515 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3516 emitToStreamer(Out, MCInstBuilder(Opcode)
3517 .addOperand(Inst.getOperand(0))
3518 .addOperand(Inst.getOperand(1))
3519 .addOperand(Inst.getOperand(2))
3520 .addReg(MCRegister())
3521 .setLoc(IDLoc));
3522 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3523 .addOperand(Inst.getOperand(0))
3524 .addOperand(Inst.getOperand(0))
3525 .addOperand(Inst.getOperand(0))
3526 .setLoc(IDLoc));
3527 } else if (Inst.getNumOperands() == 4) {
3528 // masked va >= x, vd != v0
3529 //
3530 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3531 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3532 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3533 "The destination register should not be V0.");
3534 emitToStreamer(Out, MCInstBuilder(Opcode)
3535 .addOperand(Inst.getOperand(0))
3536 .addOperand(Inst.getOperand(1))
3537 .addOperand(Inst.getOperand(2))
3538 .addOperand(Inst.getOperand(3))
3539 .setLoc(IDLoc));
3540 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3541 .addOperand(Inst.getOperand(0))
3542 .addOperand(Inst.getOperand(0))
3543 .addReg(RISCV::V0)
3544 .setLoc(IDLoc));
3545 } else if (Inst.getNumOperands() == 5 &&
3546 Inst.getOperand(0).getReg() == RISCV::V0) {
3547 // masked va >= x, vd == v0
3548 //
3549 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3550 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3551 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3552 "The destination register should be V0.");
3553 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3554 "The temporary vector register should not be V0.");
3555 emitToStreamer(Out, MCInstBuilder(Opcode)
3556 .addOperand(Inst.getOperand(1))
3557 .addOperand(Inst.getOperand(2))
3558 .addOperand(Inst.getOperand(3))
3559 .addReg(MCRegister())
3560 .setLoc(IDLoc));
3561 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3562 .addOperand(Inst.getOperand(0))
3563 .addOperand(Inst.getOperand(0))
3564 .addOperand(Inst.getOperand(1))
3565 .setLoc(IDLoc));
3566 } else if (Inst.getNumOperands() == 5) {
3567 // masked va >= x, any vd
3568 //
3569 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3570 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3571 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3572 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3573 "The temporary vector register should not be V0.");
3574 emitToStreamer(Out, MCInstBuilder(Opcode)
3575 .addOperand(Inst.getOperand(1))
3576 .addOperand(Inst.getOperand(2))
3577 .addOperand(Inst.getOperand(3))
3578 .addReg(MCRegister())
3579 .setLoc(IDLoc));
3580 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3581 .addOperand(Inst.getOperand(1))
3582 .addReg(RISCV::V0)
3583 .addOperand(Inst.getOperand(1))
3584 .setLoc(IDLoc));
3585 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3586 .addOperand(Inst.getOperand(0))
3587 .addOperand(Inst.getOperand(0))
3588 .addReg(RISCV::V0)
3589 .setLoc(IDLoc));
3590 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3591 .addOperand(Inst.getOperand(0))
3592 .addOperand(Inst.getOperand(1))
3593 .addOperand(Inst.getOperand(0))
3594 .setLoc(IDLoc));
3595 }
3596}
3597
3598bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3600 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
3601 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
3602 if (Inst.getOperand(2).getReg() != RISCV::X4) {
3603 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3604 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
3605 "%tprel_add modifier");
3606 }
3607
3608 return false;
3609}
3610
3611bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
3613 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
3614 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
3615 if (Inst.getOperand(0).getReg() != RISCV::X5) {
3616 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3617 return Error(ErrorLoc, "the output operand must be t0/x5 when using "
3618 "%tlsdesc_call modifier");
3619 }
3620
3621 return false;
3622}
3623
3624std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3625 return RISCVOperand::createReg(MCRegister(), llvm::SMLoc(), llvm::SMLoc());
3626}
3627
3628std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3629 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3630 llvm::SMLoc());
3631}
3632
3633std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3634 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3635 llvm::SMLoc());
3636}
3637
3638bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3640 unsigned Opcode = Inst.getOpcode();
3641
3642 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3643 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3644 MCRegister DestReg = Inst.getOperand(0).getReg();
3645 MCRegister TempReg = Inst.getOperand(1).getReg();
3646 if (DestReg == TempReg) {
3647 SMLoc Loc = Operands.back()->getStartLoc();
3648 return Error(Loc, "the temporary vector register cannot be the same as "
3649 "the destination register");
3650 }
3651 }
3652
3653 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3654 Opcode == RISCV::TH_LWD) {
3655 MCRegister Rd1 = Inst.getOperand(0).getReg();
3656 MCRegister Rd2 = Inst.getOperand(1).getReg();
3657 MCRegister Rs1 = Inst.getOperand(2).getReg();
3658 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3659 if (Rs1 == Rd1 && Rs1 == Rd2) {
3660 SMLoc Loc = Operands[1]->getStartLoc();
3661 return Error(Loc, "rs1, rd1, and rd2 cannot all be the same");
3662 }
3663 }
3664
3665 if (Opcode == RISCV::CM_MVSA01) {
3666 MCRegister Rd1 = Inst.getOperand(0).getReg();
3667 MCRegister Rd2 = Inst.getOperand(1).getReg();
3668 if (Rd1 == Rd2) {
3669 SMLoc Loc = Operands[1]->getStartLoc();
3670 return Error(Loc, "rs1 and rs2 must be different");
3671 }
3672 }
3673
3674 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3675 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3676 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3677 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3678 // depending on the data width.
3679 if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
3680 SMLoc Loc = Operands.back()->getStartLoc();
3681 return Error(Loc, "operand must be constant 3");
3682 } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
3683 SMLoc Loc = Operands.back()->getStartLoc();
3684 return Error(Loc, "operand must be constant 4");
3685 }
3686
3687 const MCInstrDesc &MCID = MII.get(Opcode);
3688 if (!(MCID.TSFlags & RISCVII::ConstraintMask))
3689 return false;
3690
3691 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3692 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3693 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3694 MCRegister VCIXDst = Inst.getOperand(0).getReg();
3695 SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
3696 if (MCID.TSFlags & RISCVII::VS1Constraint) {
3697 MCRegister VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3698 if (VCIXDst == VCIXRs1)
3699 return Error(VCIXDstLoc, "the destination vector register group cannot"
3700 " overlap the source vector register group");
3701 }
3702 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3703 MCRegister VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
3704 if (VCIXDst == VCIXRs2)
3705 return Error(VCIXDstLoc, "the destination vector register group cannot"
3706 " overlap the source vector register group");
3707 }
3708 return false;
3709 }
3710
3711 MCRegister DestReg = Inst.getOperand(0).getReg();
3712 unsigned Offset = 0;
3713 int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
3714 if (TiedOp == 0)
3715 Offset = 1;
3716
3717 // Operands[1] will be the first operand, DestReg.
3718 SMLoc Loc = Operands[1]->getStartLoc();
3719 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3720 MCRegister CheckReg = Inst.getOperand(Offset + 1).getReg();
3721 if (DestReg == CheckReg)
3722 return Error(Loc, "the destination vector register group cannot overlap"
3723 " the source vector register group");
3724 }
3725 if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
3726 MCRegister CheckReg = Inst.getOperand(Offset + 2).getReg();
3727 if (DestReg == CheckReg)
3728 return Error(Loc, "the destination vector register group cannot overlap"
3729 " the source vector register group");
3730 }
3731 if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3732 // vadc, vsbc are special cases. These instructions have no mask register.
3733 // The destination register could not be V0.
3734 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3735 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3736 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3737 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3738 Opcode == RISCV::VMERGE_VXM)
3739 return Error(Loc, "the destination vector register group cannot be V0");
3740
3741 // Regardless masked or unmasked version, the number of operands is the
3742 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3743 // actually. We need to check the last operand to ensure whether it is
3744 // masked or not.
3745 MCRegister CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3746 assert((CheckReg == RISCV::V0 || !CheckReg) &&
3747 "Unexpected register for mask operand");
3748
3749 if (DestReg == CheckReg)
3750 return Error(Loc, "the destination vector register group cannot overlap"
3751 " the mask register");
3752 }
3753 return false;
3754}
3755
3756bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
3758 MCStreamer &Out) {
3759 Inst.setLoc(IDLoc);
3760
3761 switch (Inst.getOpcode()) {
3762 default:
3763 break;
3764 case RISCV::PseudoC_ADDI_NOP:
3765 emitToStreamer(Out, MCInstBuilder(RISCV::C_NOP));
3766 return false;
3767 case RISCV::PseudoLLAImm:
3768 case RISCV::PseudoLAImm:
3769 case RISCV::PseudoLI: {
3770 MCRegister Reg = Inst.getOperand(0).getReg();
3771 const MCOperand &Op1 = Inst.getOperand(1);
3772 if (Op1.isExpr()) {
3773 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3774 // Just convert to an addi. This allows compatibility with gas.
3775 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
3776 .addReg(Reg)
3777 .addReg(RISCV::X0)
3778 .addExpr(Op1.getExpr()));
3779 return false;
3780 }
3781 int64_t Imm = Inst.getOperand(1).getImm();
3782 // On RV32 the immediate here can either be a signed or an unsigned
3783 // 32-bit number. Sign extension has to be performed to ensure that Imm
3784 // represents the expected signed 64-bit number.
3785 if (!isRV64())
3786 Imm = SignExtend64<32>(Imm);
3787 emitLoadImm(Reg, Imm, Out);
3788 return false;
3789 }
3790 case RISCV::PseudoLLA:
3791 emitLoadLocalAddress(Inst, IDLoc, Out);
3792 return false;
3793 case RISCV::PseudoLGA:
3794 emitLoadGlobalAddress(Inst, IDLoc, Out);
3795 return false;
3796 case RISCV::PseudoLA:
3797 emitLoadAddress(Inst, IDLoc, Out);
3798 return false;
3799 case RISCV::PseudoLA_TLS_IE:
3800 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3801 return false;
3802 case RISCV::PseudoLA_TLS_GD:
3803 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3804 return false;
3805 case RISCV::PseudoLB:
3806 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
3807 return false;
3808 case RISCV::PseudoLBU:
3809 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
3810 return false;
3811 case RISCV::PseudoLH:
3812 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
3813 return false;
3814 case RISCV::PseudoLHU:
3815 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
3816 return false;
3817 case RISCV::PseudoLW:
3818 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
3819 return false;
3820 case RISCV::PseudoLWU:
3821 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
3822 return false;
3823 case RISCV::PseudoLD:
3824 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
3825 return false;
3826 case RISCV::PseudoFLH:
3827 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3828 return false;
3829 case RISCV::PseudoFLW:
3830 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
3831 return false;
3832 case RISCV::PseudoFLD:
3833 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
3834 return false;
3835 case RISCV::PseudoSB:
3836 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
3837 return false;
3838 case RISCV::PseudoSH:
3839 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
3840 return false;
3841 case RISCV::PseudoSW:
3842 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
3843 return false;
3844 case RISCV::PseudoSD:
3845 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
3846 return false;
3847 case RISCV::PseudoFSH:
3848 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3849 return false;
3850 case RISCV::PseudoFSW:
3851 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
3852 return false;
3853 case RISCV::PseudoFSD:
3854 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
3855 return false;
3856 case RISCV::PseudoAddTPRel:
3857 if (checkPseudoAddTPRel(Inst, Operands))
3858 return true;
3859 break;
3860 case RISCV::PseudoTLSDESCCall:
3861 if (checkPseudoTLSDESCCall(Inst, Operands))
3862 return true;
3863 break;
3864 case RISCV::PseudoSEXT_B:
3865 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3866 return false;
3867 case RISCV::PseudoSEXT_H:
3868 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3869 return false;
3870 case RISCV::PseudoZEXT_H:
3871 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3872 return false;
3873 case RISCV::PseudoZEXT_W:
3874 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3875 return false;
3876 case RISCV::PseudoVMSGEU_VX:
3877 case RISCV::PseudoVMSGEU_VX_M:
3878 case RISCV::PseudoVMSGEU_VX_M_T:
3879 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3880 return false;
3881 case RISCV::PseudoVMSGE_VX:
3882 case RISCV::PseudoVMSGE_VX_M:
3883 case RISCV::PseudoVMSGE_VX_M_T:
3884 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3885 return false;
3886 case RISCV::PseudoVMSGE_VI:
3887 case RISCV::PseudoVMSLT_VI: {
3888 // These instructions are signed and so is immediate so we can subtract one
3889 // and change the opcode.
3890 int64_t Imm = Inst.getOperand(2).getImm();
3891 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3892 : RISCV::VMSLE_VI;
3893 emitToStreamer(Out, MCInstBuilder(Opc)
3894 .addOperand(Inst.getOperand(0))
3895 .addOperand(Inst.getOperand(1))
3896 .addImm(Imm - 1)
3897 .addOperand(Inst.getOperand(3))
3898 .setLoc(IDLoc));
3899 return false;
3900 }
3901 case RISCV::PseudoVMSGEU_VI:
3902 case RISCV::PseudoVMSLTU_VI: {
3903 int64_t Imm = Inst.getOperand(2).getImm();
3904 // Unsigned comparisons are tricky because the immediate is signed. If the
3905 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3906 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3907 // vmsne v0, v1, v1 which is always false.
3908 if (Imm == 0) {
3909 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3910 ? RISCV::VMSEQ_VV
3911 : RISCV::VMSNE_VV;
3912 emitToStreamer(Out, MCInstBuilder(Opc)
3913 .addOperand(Inst.getOperand(0))
3914 .addOperand(Inst.getOperand(1))
3915 .addOperand(Inst.getOperand(1))
3916 .addOperand(Inst.getOperand(3))
3917 .setLoc(IDLoc));
3918 } else {
3919 // Other immediate values can subtract one like signed.
3920 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3921 ? RISCV::VMSGTU_VI
3922 : RISCV::VMSLEU_VI;
3923 emitToStreamer(Out, MCInstBuilder(Opc)
3924 .addOperand(Inst.getOperand(0))
3925 .addOperand(Inst.getOperand(1))
3926 .addImm(Imm - 1)
3927 .addOperand(Inst.getOperand(3))
3928 .setLoc(IDLoc));
3929 }
3930
3931 return false;
3932 }
3933 }
3934
3935 emitToStreamer(Out, Inst);
3936 return false;
3937}
3938
3942}
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:257
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:188
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.