49#define DEBUG_TYPE "riscv-asm-parser"
52 "Number of RISC-V Compressed instructions emitted");
64struct ParserOptionsSet {
71 enum class VTypeState {
82 ParserOptionsSet ParserOptions;
87 bool enableExperimentalExtension()
const {
93 "do not have a target streamer");
99 unsigned Kind)
override;
104 bool generateImmOutOfRangeError(
SMLoc ErrorLoc, int64_t
Lower, int64_t
Upper,
110 bool MatchingInlineAsm)
override;
115 SMLoc &EndLoc)
override;
122 bool parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
unsigned &Sew,
123 unsigned &Lmul,
bool &Fractional,
bool &TailAgnostic,
124 bool &MaskAgnostic,
bool &AltFmt);
125 bool generateVTypeError(
SMLoc ErrorLoc);
127 bool generateXSfmmVTypeError(
SMLoc ErrorLoc);
160 void emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
164 void emitPseudoExtend(
MCInst &Inst,
bool SignExtend, int64_t Width,
193#define GET_ASSEMBLER_HEADER
194#include "RISCVGenAsmMatcher.inc"
220 return parseRegList(
Operands,
true);
227 bool ExpectNegative =
false);
229 return parseZcmpStackAdj(
Operands,
true);
233 bool parseExprWithSpecifier(
const MCExpr *&Res,
SMLoc &E);
236 bool parseDirectiveOption();
237 bool parseDirectiveAttribute();
238 bool parseDirectiveInsn(
SMLoc L);
239 bool parseDirectiveVariantCC();
245 bool FromOptionDirective);
248 if (!(
getSTI().hasFeature(Feature))) {
256 if (
getSTI().hasFeature(Feature)) {
263 void pushFeatureBits() {
265 "These two stacks must be kept synchronized");
267 ParserOptionsStack.
push_back(ParserOptions);
270 bool popFeatureBits() {
272 "These two stacks must be kept synchronized");
273 if (FeatureBitStack.
empty())
285 std::unique_ptr<RISCVOperand> defaultMaskRegOp()
const;
286 std::unique_ptr<RISCVOperand> defaultFRMArgOp()
const;
287 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp()
const;
290 enum RISCVMatchResultTy :
unsigned {
292#define GET_OPERAND_DIAGNOSTIC_TYPES
293#include "RISCVGenAsmMatcher.inc"
294#undef GET_OPERAND_DIAGNOSTIC_TYPES
298 static bool isSymbolDiff(
const MCExpr *Expr);
312 if (ABIName.ends_with(
"f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
313 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
314 "doesn't support the F instruction set extension (ignoring "
316 }
else if (ABIName.ends_with(
"d") &&
317 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
318 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
319 "doesn't support the D instruction set extension (ignoring "
332 getTargetStreamer().emitTargetAttributes(STI,
false);
401 SMLoc StartLoc, EndLoc;
416 RISCVOperand(KindTy K) :
Kind(
K) {}
421 StartLoc =
o.StartLoc;
424 case KindTy::Register:
427 case KindTy::Immediate:
430 case KindTy::FPImmediate:
436 case KindTy::SystemRegister:
448 case KindTy::RegList:
451 case KindTy::StackAdj:
452 StackAdj =
o.StackAdj;
460 bool isToken()
const override {
return Kind == KindTy::Token; }
461 bool isReg()
const override {
return Kind == KindTy::Register; }
462 bool isV0Reg()
const {
463 return Kind == KindTy::Register &&
Reg.RegNum == RISCV::V0;
465 bool isAnyReg()
const {
466 return Kind == KindTy::Register &&
467 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum) ||
468 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg.RegNum) ||
469 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg.RegNum));
471 bool isAnyRegC()
const {
472 return Kind == KindTy::Register &&
473 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
475 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
478 bool isImm()
const override {
return Kind == KindTy::Immediate; }
479 bool isMem()
const override {
return false; }
480 bool isSystemRegister()
const {
return Kind == KindTy::SystemRegister; }
481 bool isRegReg()
const {
return Kind == KindTy::RegReg; }
482 bool isRegList()
const {
return Kind == KindTy::RegList; }
483 bool isRegListS0()
const {
486 bool isStackAdj()
const {
return Kind == KindTy::StackAdj; }
489 return Kind == KindTy::Register &&
490 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum);
493 bool isGPRPair()
const {
494 return Kind == KindTy::Register &&
495 RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
499 bool isGPRPairC()
const {
500 return Kind == KindTy::Register &&
501 RISCVMCRegisterClasses[RISCV::GPRPairCRegClassID].contains(
505 bool isGPRPairNoX0()
const {
506 return Kind == KindTy::Register &&
507 RISCVMCRegisterClasses[RISCV::GPRPairNoX0RegClassID].contains(
511 bool isGPRF16()
const {
512 return Kind == KindTy::Register &&
513 RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(
Reg.RegNum);
516 bool isGPRF32()
const {
517 return Kind == KindTy::Register &&
518 RISCVMCRegisterClasses[RISCV::GPRF32RegClassID].contains(
Reg.RegNum);
521 bool isGPRAsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
522 bool isGPRAsFPR16()
const {
return isGPRF16() &&
Reg.IsGPRAsFPR; }
523 bool isGPRAsFPR32()
const {
return isGPRF32() &&
Reg.IsGPRAsFPR; }
524 bool isGPRPairAsFPR64()
const {
return isGPRPair() &&
Reg.IsGPRAsFPR; }
526 static bool evaluateConstantImm(
const MCExpr *Expr, int64_t &Imm) {
527 if (
auto CE = dyn_cast<MCConstantExpr>(Expr)) {
528 Imm =
CE->getValue();
537 template <
int N>
bool isBareSimmNLsb0()
const {
542 if (evaluateConstantImm(
getImm(), Imm))
543 return isShiftedInt<
N - 1, 1>(fixImmediateForRV32(Imm, isRV64Imm()));
546 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
552 template <
int N>
bool isBareSimmN()
const {
557 if (evaluateConstantImm(
getImm(), Imm))
558 return isInt<N>(fixImmediateForRV32(Imm, isRV64Imm()));
561 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
567 bool isBareSymbol()
const {
570 if (!isImm() || evaluateConstantImm(
getImm(), Imm))
574 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
578 bool isCallSymbol()
const {
581 if (!isImm() || evaluateConstantImm(
getImm(), Imm))
585 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
586 VK == ELF::R_RISCV_CALL_PLT;
589 bool isPseudoJumpSymbol()
const {
592 if (!isImm() || evaluateConstantImm(
getImm(), Imm))
596 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
597 VK == ELF::R_RISCV_CALL_PLT;
600 bool isTPRelAddSymbol()
const {
603 if (!isImm() || evaluateConstantImm(
getImm(), Imm))
607 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
608 VK == ELF::R_RISCV_TPREL_ADD;
611 bool isTLSDESCCallSymbol()
const {
614 if (!isImm() || evaluateConstantImm(
getImm(), Imm))
618 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
619 VK == ELF::R_RISCV_TLSDESC_CALL;
622 bool isCSRSystemRegister()
const {
return isSystemRegister(); }
626 bool isVTypeI10()
const {
627 if (Kind == KindTy::VType)
631 bool isVTypeI11()
const {
632 if (Kind == KindTy::VType)
637 bool isXSfmmVType()
const {
643 bool isFenceArg()
const {
return Kind == KindTy::Fence; }
646 bool isFRMArg()
const {
return Kind == KindTy::FRM; }
647 bool isFRMArgLegacy()
const {
return Kind == KindTy::FRM; }
651 bool isLoadFPImm()
const {
654 if (Kind != KindTy::FPImmediate)
657 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
660 return Idx >= 0 &&
Idx != 1;
663 bool isImmXLenLI()
const {
669 if (evaluateConstantImm(
getImm(), Imm))
670 return isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm));
672 return RISCVAsmParser::isSymbolDiff(
getImm());
675 bool isImmXLenLI_Restricted()
const {
679 bool IsConstantImm = evaluateConstantImm(
getImm(), Imm);
681 return IsConstantImm &&
682 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
685 template <
unsigned N>
bool isUImm()
const {
689 bool IsConstantImm = evaluateConstantImm(
getImm(), Imm);
690 return IsConstantImm && isUInt<N>(Imm);
693 template <
unsigned N,
unsigned S>
bool isUImmShifted()
const {
697 bool IsConstantImm = evaluateConstantImm(
getImm(), Imm);
698 return IsConstantImm && isShiftedUInt<N, S>(Imm);
701 template <
class Pred>
bool isUImmPred(Pred p)
const {
705 bool IsConstantImm = evaluateConstantImm(
getImm(), Imm);
706 return IsConstantImm &&
p(Imm);
709 bool isUImmLog2XLen()
const {
710 if (isImm() && isRV64Imm())
715 bool isUImmLog2XLenNonZero()
const {
716 if (isImm() && isRV64Imm())
717 return isUImmPred([](int64_t Imm) {
return Imm != 0 && isUInt<6>(Imm); });
718 return isUImmPred([](int64_t Imm) {
return Imm != 0 && isUInt<5>(Imm); });
721 bool isUImmLog2XLenHalf()
const {
722 if (isImm() && isRV64Imm())
727 bool isUImm1()
const {
return isUImm<1>(); }
728 bool isUImm2()
const {
return isUImm<2>(); }
729 bool isUImm3()
const {
return isUImm<3>(); }
730 bool isUImm4()
const {
return isUImm<4>(); }
731 bool isUImm5()
const {
return isUImm<5>(); }
732 bool isUImm6()
const {
return isUImm<6>(); }
733 bool isUImm7()
const {
return isUImm<7>(); }
734 bool isUImm8()
const {
return isUImm<8>(); }
735 bool isUImm9()
const {
return isUImm<9>(); }
736 bool isUImm10()
const {
return isUImm<10>(); }
737 bool isUImm11()
const {
return isUImm<11>(); }
738 bool isUImm16()
const {
return isUImm<16>(); }
739 bool isUImm20()
const {
return isUImm<20>(); }
740 bool isUImm32()
const {
return isUImm<32>(); }
741 bool isUImm48()
const {
return isUImm<48>(); }
742 bool isUImm64()
const {
return isUImm<64>(); }
744 bool isUImm5NonZero()
const {
745 return isUImmPred([](int64_t Imm) {
return Imm != 0 && isUInt<5>(Imm); });
748 bool isUImm5GT3()
const {
749 return isUImmPred([](int64_t Imm) {
return isUInt<5>(Imm) &&
Imm > 3; });
752 bool isUImm5Plus1()
const {
754 [](int64_t Imm) {
return Imm > 0 && isUInt<5>(Imm - 1); });
757 bool isUImm5GE6Plus1()
const {
759 [](int64_t Imm) {
return Imm >= 6 && isUInt<5>(Imm - 1); });
762 bool isUImm5Slist()
const {
763 return isUImmPred([](int64_t Imm) {
764 return (Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
765 (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31);
769 bool isUImm8GE32()
const {
770 return isUImmPred([](int64_t Imm) {
return isUInt<8>(Imm) &&
Imm >= 32; });
773 bool isRnumArg()
const {
775 [](int64_t Imm) {
return Imm >= INT64_C(0) &&
Imm <= INT64_C(10); });
778 bool isRnumArg_0_7()
const {
780 [](int64_t Imm) {
return Imm >= INT64_C(0) &&
Imm <= INT64_C(7); });
783 bool isRnumArg_1_10()
const {
785 [](int64_t Imm) {
return Imm >= INT64_C(1) &&
Imm <= INT64_C(10); });
788 bool isRnumArg_2_14()
const {
790 [](int64_t Imm) {
return Imm >= INT64_C(2) &&
Imm <= INT64_C(14); });
793 template <
unsigned N>
bool isSImm()
const {
797 bool IsConstantImm = evaluateConstantImm(
getImm(), Imm);
798 return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Imm()));
801 template <
class Pred>
bool isSImmPred(Pred p)
const {
805 bool IsConstantImm = evaluateConstantImm(
getImm(), Imm);
806 return IsConstantImm &&
p(fixImmediateForRV32(Imm, isRV64Imm()));
809 bool isSImm5()
const {
return isSImm<5>(); }
810 bool isSImm6()
const {
return isSImm<6>(); }
811 bool isSImm10()
const {
return isSImm<10>(); }
812 bool isSImm11()
const {
return isSImm<11>(); }
813 bool isSImm16()
const {
return isSImm<16>(); }
814 bool isSImm26()
const {
return isSImm<26>(); }
816 bool isSImm5NonZero()
const {
817 return isSImmPred([](int64_t Imm) {
return Imm != 0 && isInt<5>(Imm); });
820 bool isSImm6NonZero()
const {
821 return isSImmPred([](int64_t Imm) {
return Imm != 0 && isInt<6>(Imm); });
824 bool isCLUIImm()
const {
825 return isUImmPred([](int64_t Imm) {
826 return (isUInt<5>(Imm) && Imm != 0) || (Imm >= 0xfffe0 && Imm <= 0xfffff);
830 bool isUImm2Lsb0()
const {
return isUImmShifted<1, 1>(); }
832 bool isUImm5Lsb0()
const {
return isUImmShifted<4, 1>(); }
834 bool isUImm6Lsb0()
const {
return isUImmShifted<5, 1>(); }
836 bool isUImm7Lsb00()
const {
return isUImmShifted<5, 2>(); }
838 bool isUImm7Lsb000()
const {
return isUImmShifted<4, 3>(); }
840 bool isUImm8Lsb00()
const {
return isUImmShifted<6, 2>(); }
842 bool isUImm8Lsb000()
const {
return isUImmShifted<5, 3>(); }
844 bool isUImm9Lsb000()
const {
return isUImmShifted<6, 3>(); }
846 bool isUImm14Lsb00()
const {
return isUImmShifted<12, 2>(); }
848 bool isUImm10Lsb00NonZero()
const {
850 [](int64_t Imm) {
return isShiftedUInt<8, 2>(Imm) && (
Imm != 0); });
855 static int64_t fixImmediateForRV32(int64_t Imm,
bool IsRV64Imm) {
856 if (IsRV64Imm || !isUInt<32>(Imm))
858 return SignExtend64<32>(Imm);
861 bool isSImm12()
const {
866 if (evaluateConstantImm(
getImm(), Imm))
867 return isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
870 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
873 VK == ELF::R_RISCV_TLSDESC_ADD_LO12);
876 bool isSImm12Lsb00000()
const {
877 return isSImmPred([](int64_t Imm) {
return isShiftedInt<7, 5>(Imm); });
880 bool isSImm10Lsb0000NonZero()
const {
882 [](int64_t Imm) {
return Imm != 0 && isShiftedInt<6, 4>(Imm); });
885 bool isSImm16NonZero()
const {
886 return isSImmPred([](int64_t Imm) {
return Imm != 0 && isInt<16>(Imm); });
889 bool isUImm16NonZero()
const {
890 return isUImmPred([](int64_t Imm) {
return isUInt<16>(Imm) &&
Imm != 0; });
893 bool isSImm20LI()
const {
898 if (evaluateConstantImm(
getImm(), Imm))
899 return isInt<20>(fixImmediateForRV32(Imm, isRV64Imm()));
902 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
906 bool isSImm8Unsigned()
const {
return isSImm<8>() || isUImm<8>(); }
907 bool isSImm10Unsigned()
const {
return isSImm<10>() || isUImm<10>(); }
909 bool isUImm20LUI()
const {
914 if (evaluateConstantImm(
getImm(), Imm))
915 return isUInt<20>(Imm);
918 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
919 (VK == ELF::R_RISCV_HI20 || VK == ELF::R_RISCV_TPREL_HI20);
922 bool isUImm20AUIPC()
const {
927 if (evaluateConstantImm(
getImm(), Imm))
928 return isUInt<20>(Imm);
931 return RISCVAsmParser::classifySymbolRef(
getImm(), VK) &&
932 (VK == ELF::R_RISCV_PCREL_HI20 || VK == ELF::R_RISCV_GOT_HI20 ||
933 VK == ELF::R_RISCV_TLS_GOT_HI20 || VK == ELF::R_RISCV_TLS_GD_HI20 ||
934 VK == ELF::R_RISCV_TLSDESC_HI20);
937 bool isImmZero()
const {
938 return isUImmPred([](int64_t Imm) {
return 0 ==
Imm; });
941 bool isImmThree()
const {
942 return isUImmPred([](int64_t Imm) {
return 3 ==
Imm; });
945 bool isImmFour()
const {
946 return isUImmPred([](int64_t Imm) {
return 4 ==
Imm; });
949 bool isSImm5Plus1()
const {
951 [](int64_t Imm) {
return Imm !=
INT64_MIN && isInt<5>(Imm - 1); });
954 bool isSImm18()
const {
955 return isSImmPred([](int64_t Imm) {
return isInt<18>(Imm); });
958 bool isSImm18Lsb0()
const {
959 return isSImmPred([](int64_t Imm) {
return isShiftedInt<17, 1>(Imm); });
962 bool isSImm19Lsb00()
const {
963 return isSImmPred([](int64_t Imm) {
return isShiftedInt<17, 2>(Imm); });
966 bool isSImm20Lsb000()
const {
967 return isSImmPred([](int64_t Imm) {
return isShiftedInt<17, 3>(Imm); });
970 bool isSImm32Lsb0()
const {
971 return isSImmPred([](int64_t Imm) {
return isShiftedInt<31, 1>(Imm); });
975 SMLoc getStartLoc()
const override {
return StartLoc; }
977 SMLoc getEndLoc()
const override {
return EndLoc; }
979 bool isRV64Imm()
const {
980 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
985 assert(Kind == KindTy::Register &&
"Invalid type access!");
990 assert(Kind == KindTy::SystemRegister &&
"Invalid type access!");
991 return StringRef(SysReg.Data, SysReg.Length);
995 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1000 assert(Kind == KindTy::FPImmediate &&
"Invalid type access!");
1005 assert(Kind == KindTy::Token &&
"Invalid type access!");
1009 unsigned getVType()
const {
1010 assert(Kind == KindTy::VType &&
"Invalid type access!");
1015 assert(Kind == KindTy::FRM &&
"Invalid type access!");
1019 unsigned getFence()
const {
1020 assert(Kind == KindTy::Fence &&
"Invalid type access!");
1033 case KindTy::Immediate:
1036 OS <<
' ' << (
Imm.IsRV64 ?
"rv64" :
"rv32") <<
'>';
1038 case KindTy::FPImmediate:
1039 OS <<
"<fpimm: " << FPImm.Val <<
">";
1041 case KindTy::Register:
1043 << (
Reg.IsGPRAsFPR ?
") GPRasFPR>" :
")>");
1046 OS <<
"'" << getToken() <<
"'";
1048 case KindTy::SystemRegister:
1049 OS <<
"<sysreg: " << getSysReg() <<
" (" << SysReg.Encoding <<
")>";
1058 roundingModeToString(getFRM());
1066 case KindTy::RegList:
1071 case KindTy::StackAdj:
1072 OS <<
"<stackadj: ";
1076 case KindTy::RegReg:
1083 static std::unique_ptr<RISCVOperand> createToken(
StringRef Str,
SMLoc S) {
1084 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1091 static std::unique_ptr<RISCVOperand>
1093 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1094 Op->Reg.RegNum =
Reg;
1095 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1101 static std::unique_ptr<RISCVOperand> createImm(
const MCExpr *Val,
SMLoc S,
1102 SMLoc E,
bool IsRV64) {
1103 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1105 Op->Imm.IsRV64 = IsRV64;
1111 static std::unique_ptr<RISCVOperand> createFPImm(
uint64_t Val,
SMLoc S) {
1112 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1113 Op->FPImm.Val = Val;
1119 static std::unique_ptr<RISCVOperand> createSysReg(
StringRef Str,
SMLoc S,
1120 unsigned Encoding) {
1121 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1122 Op->SysReg.Data = Str.data();
1123 Op->SysReg.Length = Str.size();
1130 static std::unique_ptr<RISCVOperand>
1132 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1139 static std::unique_ptr<RISCVOperand> createFenceArg(
unsigned Val,
SMLoc S) {
1140 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1141 Op->Fence.Val = Val;
1147 static std::unique_ptr<RISCVOperand> createVType(
unsigned VTypeI,
SMLoc S) {
1148 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1149 Op->VType.Val = VTypeI;
1155 static std::unique_ptr<RISCVOperand> createRegList(
unsigned RlistEncode,
1157 auto Op = std::make_unique<RISCVOperand>(KindTy::RegList);
1163 static std::unique_ptr<RISCVOperand>
1165 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1167 Op->RegReg.OffsetReg = OffsetReg;
1173 static std::unique_ptr<RISCVOperand> createStackAdj(
unsigned StackAdj,
SMLoc S) {
1174 auto Op = std::make_unique<RISCVOperand>(KindTy::StackAdj);
1175 Op->StackAdj.Val = StackAdj;
1180 static void addExpr(
MCInst &Inst,
const MCExpr *Expr,
bool IsRV64Imm) {
1181 assert(Expr &&
"Expr shouldn't be null!");
1183 bool IsConstant = evaluateConstantImm(Expr, Imm);
1193 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
1194 assert(
N == 1 &&
"Invalid number of operands!");
1198 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
1199 assert(
N == 1 &&
"Invalid number of operands!");
1200 addExpr(Inst,
getImm(), isRV64Imm());
1203 void addSImm8UnsignedOperands(
MCInst &Inst,
unsigned N)
const {
1204 assert(
N == 1 &&
"Invalid number of operands!");
1211 void addSImm10UnsignedOperands(
MCInst &Inst,
unsigned N)
const {
1212 assert(
N == 1 &&
"Invalid number of operands!");
1219 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
1220 assert(
N == 1 &&
"Invalid number of operands!");
1222 addExpr(Inst,
getImm(), isRV64Imm());
1227 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
1231 void addFenceArgOperands(
MCInst &Inst,
unsigned N)
const {
1232 assert(
N == 1 &&
"Invalid number of operands!");
1236 void addCSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
1237 assert(
N == 1 &&
"Invalid number of operands!");
1244 void addVTypeIOperands(
MCInst &Inst,
unsigned N)
const {
1245 assert(
N == 1 &&
"Invalid number of operands!");
1247 if (Kind == KindTy::Immediate) {
1248 [[maybe_unused]]
bool IsConstantImm = evaluateConstantImm(
getImm(), Imm);
1249 assert(IsConstantImm &&
"Invalid VTypeI Operand!");
1256 void addRegListOperands(
MCInst &Inst,
unsigned N)
const {
1257 assert(
N == 1 &&
"Invalid number of operands!");
1261 void addRegRegOperands(
MCInst &Inst,
unsigned N)
const {
1262 assert(
N == 2 &&
"Invalid number of operands!");
1267 void addStackAdjOperands(
MCInst &Inst,
unsigned N)
const {
1268 assert(
N == 1 &&
"Invalid number of operands!");
1272 void addFRMArgOperands(
MCInst &Inst,
unsigned N)
const {
1273 assert(
N == 1 &&
"Invalid number of operands!");
1279#define GET_REGISTER_MATCHER
1280#define GET_SUBTARGET_FEATURE_NAME
1281#define GET_MATCHER_IMPLEMENTATION
1282#define GET_MNEMONIC_SPELL_CHECKER
1283#include "RISCVGenAsmMatcher.inc"
1286 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D &&
"Invalid register");
1287 return Reg - RISCV::F0_D + RISCV::F0_H;
1291 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D &&
"Invalid register");
1292 return Reg - RISCV::F0_D + RISCV::F0_F;
1296 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D &&
"Invalid register");
1297 return Reg - RISCV::F0_D + RISCV::F0_Q;
1302 unsigned RegClassID;
1303 if (Kind == MCK_VRM2)
1304 RegClassID = RISCV::VRM2RegClassID;
1305 else if (Kind == MCK_VRM4)
1306 RegClassID = RISCV::VRM4RegClassID;
1307 else if (Kind == MCK_VRM8)
1308 RegClassID = RISCV::VRM8RegClassID;
1312 &RISCVMCRegisterClasses[RegClassID]);
1317 RISCVOperand &
Op =
static_cast<RISCVOperand &
>(AsmOp);
1319 return Match_InvalidOperand;
1323 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1325 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1326 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1328 if (IsRegFPR64 && Kind == MCK_FPR128) {
1330 return Match_Success;
1334 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1335 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1337 return Match_Success;
1341 if (IsRegFPR64 && Kind == MCK_FPR16) {
1343 return Match_Success;
1345 if (Kind == MCK_GPRAsFPR16 &&
Op.isGPRAsFPR()) {
1346 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_H;
1347 return Match_Success;
1349 if (Kind == MCK_GPRAsFPR32 &&
Op.isGPRAsFPR()) {
1350 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_W;
1351 return Match_Success;
1358 if (RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(Reg) &&
1359 Kind == MCK_GPRF64AsFPR && STI->
hasFeature(RISCV::FeatureStdExtZdinx) &&
1361 return Match_Success;
1365 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1368 return Match_InvalidOperand;
1369 return Match_Success;
1371 return Match_InvalidOperand;
1374bool RISCVAsmParser::generateImmOutOfRangeError(
1376 const Twine &Msg =
"immediate must be an integer in the range") {
1380bool RISCVAsmParser::generateImmOutOfRangeError(
1382 const Twine &Msg =
"immediate must be an integer in the range") {
1384 return generateImmOutOfRangeError(ErrorLoc,
Lower,
Upper, Msg);
1387bool RISCVAsmParser::matchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1391 bool MatchingInlineAsm) {
1401 if (validateInstruction(Inst,
Operands))
1403 return processInstruction(Inst, IDLoc,
Operands, Out);
1404 case Match_MissingFeature: {
1405 assert(MissingFeatures.
any() &&
"Unknown missing features!");
1406 bool FirstFeature =
true;
1407 std::string Msg =
"instruction requires the following:";
1408 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
1409 if (MissingFeatures[i]) {
1410 Msg += FirstFeature ?
" " :
", ";
1412 FirstFeature =
false;
1415 return Error(IDLoc, Msg);
1417 case Match_MnemonicFail: {
1418 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1419 std::string Suggestion = RISCVMnemonicSpellCheck(
1420 ((RISCVOperand &)*
Operands[0]).getToken(), FBS, 0);
1421 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
1423 case Match_InvalidOperand: {
1424 SMLoc ErrorLoc = IDLoc;
1427 return Error(ErrorLoc,
"too few operands for instruction");
1430 if (ErrorLoc ==
SMLoc())
1433 return Error(ErrorLoc,
"invalid operand for instruction");
1440 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1441 SMLoc ErrorLoc = IDLoc;
1443 return Error(ErrorLoc,
"too few operands for instruction");
1449 case Match_InvalidImmXLenLI:
1452 return Error(ErrorLoc,
"operand must be a constant 64-bit integer");
1455 std::numeric_limits<int32_t>::min(),
1456 std::numeric_limits<uint32_t>::max());
1457 case Match_InvalidImmXLenLI_Restricted:
1460 return Error(ErrorLoc,
"operand either must be a constant 64-bit integer "
1461 "or a bare symbol name");
1463 return generateImmOutOfRangeError(
1465 std::numeric_limits<uint32_t>::max(),
1466 "operand either must be a bare symbol name or an immediate integer in "
1468 case Match_InvalidUImmLog2XLen:
1472 case Match_InvalidUImmLog2XLenNonZero:
1476 case Match_InvalidUImm1:
1478 case Match_InvalidUImm2:
1480 case Match_InvalidUImm2Lsb0:
1482 "immediate must be one of");
1483 case Match_InvalidUImm3:
1485 case Match_InvalidUImm4:
1487 case Match_InvalidUImm5:
1489 case Match_InvalidUImm5NonZero:
1491 case Match_InvalidUImm5GT3:
1493 case Match_InvalidUImm5Plus1:
1495 case Match_InvalidUImm5GE6Plus1:
1497 case Match_InvalidUImm5Slist: {
1499 return Error(ErrorLoc,
1500 "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");
1502 case Match_InvalidUImm6:
1504 case Match_InvalidUImm7:
1506 case Match_InvalidUImm8:
1508 case Match_InvalidUImm8GE32:
1510 case Match_InvalidSImm5:
1513 case Match_InvalidSImm5NonZero:
1514 return generateImmOutOfRangeError(
1516 "immediate must be non-zero in the range");
1517 case Match_InvalidSImm6:
1520 case Match_InvalidSImm6NonZero:
1521 return generateImmOutOfRangeError(
1523 "immediate must be non-zero in the range");
1524 case Match_InvalidCLUIImm:
1525 return generateImmOutOfRangeError(
1527 "immediate must be in [0xfffe0, 0xfffff] or");
1528 case Match_InvalidUImm5Lsb0:
1529 return generateImmOutOfRangeError(
1531 "immediate must be a multiple of 2 bytes in the range");
1532 case Match_InvalidUImm6Lsb0:
1533 return generateImmOutOfRangeError(
1535 "immediate must be a multiple of 2 bytes in the range");
1536 case Match_InvalidUImm7Lsb00:
1537 return generateImmOutOfRangeError(
1539 "immediate must be a multiple of 4 bytes in the range");
1540 case Match_InvalidUImm8Lsb00:
1541 return generateImmOutOfRangeError(
1543 "immediate must be a multiple of 4 bytes in the range");
1544 case Match_InvalidUImm8Lsb000:
1545 return generateImmOutOfRangeError(
1547 "immediate must be a multiple of 8 bytes in the range");
1548 case Match_InvalidUImm9:
1550 "immediate offset must be in the range");
1551 case Match_InvalidBareSImm9Lsb0:
1552 return generateImmOutOfRangeError(
1554 "immediate must be a multiple of 2 bytes in the range");
1555 case Match_InvalidUImm9Lsb000:
1556 return generateImmOutOfRangeError(
1558 "immediate must be a multiple of 8 bytes in the range");
1559 case Match_InvalidSImm8Unsigned:
1562 case Match_InvalidSImm10:
1565 case Match_InvalidSImm10Unsigned:
1568 case Match_InvalidUImm10Lsb00NonZero:
1569 return generateImmOutOfRangeError(
1571 "immediate must be a multiple of 4 bytes in the range");
1572 case Match_InvalidSImm10Lsb0000NonZero:
1573 return generateImmOutOfRangeError(
1575 "immediate must be a multiple of 16 bytes and non-zero in the range");
1576 case Match_InvalidSImm11:
1579 case Match_InvalidBareSImm11Lsb0:
1580 return generateImmOutOfRangeError(
1582 "immediate must be a multiple of 2 bytes in the range");
1583 case Match_InvalidUImm10:
1585 case Match_InvalidUImm11:
1587 case Match_InvalidUImm14Lsb00:
1588 return generateImmOutOfRangeError(
1590 "immediate must be a multiple of 4 bytes in the range");
1591 case Match_InvalidUImm16NonZero:
1593 case Match_InvalidSImm12:
1594 return generateImmOutOfRangeError(
1596 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo specifier or an "
1597 "integer in the range");
1598 case Match_InvalidBareSImm12Lsb0:
1599 return generateImmOutOfRangeError(
1601 "immediate must be a multiple of 2 bytes in the range");
1602 case Match_InvalidSImm12Lsb00000:
1603 return generateImmOutOfRangeError(
1605 "immediate must be a multiple of 32 bytes in the range");
1606 case Match_InvalidBareSImm13Lsb0:
1607 return generateImmOutOfRangeError(
1609 "immediate must be a multiple of 2 bytes in the range");
1610 case Match_InvalidSImm16:
1613 case Match_InvalidSImm16NonZero:
1614 return generateImmOutOfRangeError(
1616 "immediate must be non-zero in the range");
1617 case Match_InvalidSImm20LI:
1618 return generateImmOutOfRangeError(
1620 "operand must be a symbol with a %qc.abs20 specifier or an integer "
1622 case Match_InvalidUImm20LUI:
1623 return generateImmOutOfRangeError(
1625 "operand must be a symbol with "
1626 "%hi/%tprel_hi specifier or an integer in "
1628 case Match_InvalidUImm20:
1630 case Match_InvalidUImm20AUIPC:
1631 return generateImmOutOfRangeError(
1633 "operand must be a symbol with a "
1634 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi specifier "
1636 "an integer in the range");
1637 case Match_InvalidBareSImm21Lsb0:
1638 return generateImmOutOfRangeError(
1640 "immediate must be a multiple of 2 bytes in the range");
1641 case Match_InvalidCSRSystemRegister: {
1643 "operand must be a valid system register "
1644 "name or an integer in the range");
1646 case Match_InvalidVTypeI: {
1648 return generateVTypeError(ErrorLoc);
1650 case Match_InvalidSImm5Plus1: {
1653 "immediate must be in the range");
1655 case Match_InvalidSImm18:
1658 case Match_InvalidSImm18Lsb0:
1659 return generateImmOutOfRangeError(
1661 "immediate must be a multiple of 2 bytes in the range");
1662 case Match_InvalidSImm19Lsb00:
1663 return generateImmOutOfRangeError(
1665 "immediate must be a multiple of 4 bytes in the range");
1666 case Match_InvalidSImm20Lsb000:
1667 return generateImmOutOfRangeError(
1669 "immediate must be a multiple of 8 bytes in the range");
1670 case Match_InvalidSImm26:
1674 case Match_InvalidBareSymbolQC_E_LI:
1677 case Match_InvalidBareSImm32:
1679 std::numeric_limits<int32_t>::min(),
1680 std::numeric_limits<uint32_t>::max());
1681 case Match_InvalidBareSImm32Lsb0:
1682 return generateImmOutOfRangeError(
1684 std::numeric_limits<int32_t>::max() - 1,
1685 "operand must be a multiple of 2 bytes in the range");
1686 case Match_InvalidRnumArg: {
1689 case Match_InvalidStackAdj: {
1693 "stack adjustment is invalid for this instruction and register list");
1697 if (
const char *MatchDiag = getMatchKindDiag((RISCVMatchResultTy)Result)) {
1699 return Error(ErrorLoc, MatchDiag);
1714 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1715 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1716 assert(!(Reg >= RISCV::F0_Q && Reg <= RISCV::F31_Q));
1718 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1719 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1720 static_assert(RISCV::F0_D < RISCV::F0_Q,
"FPR matching must be updated");
1723 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1730 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1731 return Error(StartLoc,
"invalid register name");
1737 const AsmToken &Tok = getParser().getTok();
1752 SMLoc FirstS = getLoc();
1753 bool HadParens =
false;
1760 size_t ReadCount = getLexer().peekTokens(Buf);
1763 LParen = getParser().getTok();
1768 switch (getLexer().getKind()) {
1771 getLexer().UnLex(LParen);
1779 getLexer().UnLex(LParen);
1783 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1785 SMLoc E = getTok().getEndLoc();
1787 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
1792 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1803 switch (getLexer().getKind()) {
1813 if (getParser().parseExpression(Res, E))
1816 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1818 int64_t
Imm =
CE->getValue();
1819 if (isUInt<7>(Imm)) {
1820 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1829 if (getParser().parseIdentifier(Identifier))
1832 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1834 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1835 "Unexpected opcode");
1838 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1848 return generateImmOutOfRangeError(
1850 "opcode must be a valid opcode name or an immediate in the range");
1858 switch (getLexer().getKind()) {
1868 if (getParser().parseExpression(Res, E))
1871 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1873 int64_t
Imm =
CE->getValue();
1874 if (Imm >= 0 && Imm <= 2) {
1875 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1884 if (getParser().parseIdentifier(Identifier))
1888 if (Identifier ==
"C0")
1890 else if (Identifier ==
"C1")
1892 else if (Identifier ==
"C2")
1899 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1908 return generateImmOutOfRangeError(
1910 "opcode must be a valid opcode name or an immediate in the range");
1917 auto SysRegFromConstantInt = [
this](
const MCExpr *E,
SMLoc S) {
1918 if (
auto *CE = dyn_cast<MCConstantExpr>(E)) {
1919 int64_t
Imm =
CE->getValue();
1920 if (isUInt<12>(Imm)) {
1921 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1924 for (
auto &Reg :
Range) {
1925 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1928 return RISCVOperand::createSysReg(
Reg.Name, S, Imm);
1932 return RISCVOperand::createSysReg(
"", S, Imm);
1935 return std::unique_ptr<RISCVOperand>();
1938 switch (getLexer().getKind()) {
1948 if (getParser().parseExpression(Res))
1951 if (
auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1952 Operands.push_back(std::move(SysOpnd));
1956 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1960 if (getParser().parseIdentifier(Identifier))
1963 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1966 if (SysReg->IsDeprecatedName) {
1968 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);
1969 for (
auto &Reg :
Range) {
1970 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1972 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
1978 const auto &FeatureBits = getSTI().getFeatureBits();
1979 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
1981 return SysReg->FeaturesRequired[Feature.Value];
1983 auto ErrorMsg = std::string(
"system register '") + SysReg->Name +
"' ";
1984 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
1985 ErrorMsg +=
"is RV32 only";
1987 ErrorMsg +=
" and ";
1991 "requires '" + std::string(Feature->Key) +
"' to be enabled";
1994 return Error(S, ErrorMsg);
1997 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
2002 MCSymbol *
Sym = getContext().lookupSymbol(Identifier);
2003 if (
Sym &&
Sym->isVariable()) {
2006 if (
auto SysOpnd = SysRegFromConstantInt(
Sym->getVariableValue(), S)) {
2007 Operands.push_back(std::move(SysOpnd));
2012 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2013 "operand must be a valid system register "
2014 "name or an integer in the range");
2018 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2031 if (
Identifier.compare_insensitive(
"inf") == 0) {
2034 getTok().getEndLoc(), isRV64()));
2035 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
2038 getTok().getEndLoc(), isRV64()));
2039 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
2042 getTok().getEndLoc(), isRV64()));
2044 return TokError(
"invalid floating point literal");
2057 return TokError(
"invalid floating point immediate");
2060 APFloat RealVal(APFloat::IEEEdouble());
2062 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
2064 return TokError(
"invalid floating point representation");
2067 RealVal.changeSign();
2069 Operands.push_back(RISCVOperand::createFPImm(
2070 RealVal.bitcastToAPInt().getZExtValue(), S));
2082 switch (getLexer().getKind()) {
2094 if (getParser().parseExpression(Res, E))
2098 return parseOperandWithSpecifier(
Operands);
2101 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2111 const MCExpr *Expr =
nullptr;
2112 bool Failed = parseExprWithSpecifier(Expr, E);
2114 Operands.push_back(RISCVOperand::createImm(Expr, S, E, isRV64()));
2118bool RISCVAsmParser::parseExprWithSpecifier(
const MCExpr *&Res,
SMLoc &E) {
2119 SMLoc Loc = getLoc();
2121 return TokError(
"expected '%' relocation specifier");
2125 return TokError(
"invalid relocation specifier");
2132 if (getParser().parseParenExpression(SubExpr, E))
2139bool RISCVAsmParser::parseDataExpr(
const MCExpr *&Res) {
2142 return parseExprWithSpecifier(Res, E);
2143 return getParser().parseExpression(Res);
2154 AsmToken Tok = getLexer().getTok();
2156 if (getParser().parseIdentifier(Identifier))
2161 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2163 if (
Sym->isVariable()) {
2165 if (!isa<MCSymbolRefExpr>(V)) {
2166 getLexer().UnLex(Tok);
2174 switch (getLexer().getKind()) {
2176 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2189 if (getParser().parseExpression(Expr, E))
2192 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2202 std::string
Identifier(getTok().getIdentifier());
2208 SMLoc Loc = getLoc();
2209 if (getParser().parseIdentifier(PLT) || PLT !=
"plt")
2210 return Error(Loc,
"@ (except the deprecated/ignored @plt) is disallowed");
2221 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2224 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2233 if (getParser().parseExpression(Res, E))
2236 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef)
2237 return Error(S,
"operand must be a valid jump target");
2240 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2261bool RISCVAsmParser::parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
2262 unsigned &Sew,
unsigned &Lmul,
2263 bool &Fractional,
bool &TailAgnostic,
2264 bool &MaskAgnostic,
bool &AltFmt) {
2269 if (State < VTypeState::SeenSew &&
Identifier.consume_front(
"e")) {
2271 if (Identifier ==
"16alt") {
2274 }
else if (Identifier ==
"8alt") {
2284 State = VTypeState::SeenSew;
2288 if (State < VTypeState::SeenLmul &&
Identifier.consume_front(
"m")) {
2291 if (Identifier ==
"a" || Identifier ==
"u") {
2293 State = VTypeState::SeenMaskPolicy;
2304 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2305 unsigned MinLMUL = ELEN / 8;
2308 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2309 Twine(MinLMUL) +
" is reserved");
2312 State = VTypeState::SeenLmul;
2316 if (State < VTypeState::SeenTailPolicy &&
Identifier.starts_with(
"t")) {
2317 if (Identifier ==
"ta")
2318 TailAgnostic =
true;
2319 else if (Identifier ==
"tu")
2320 TailAgnostic =
false;
2324 State = VTypeState::SeenTailPolicy;
2328 if (State < VTypeState::SeenMaskPolicy &&
Identifier.starts_with(
"m")) {
2329 if (Identifier ==
"ma")
2330 MaskAgnostic =
true;
2331 else if (Identifier ==
"mu")
2332 MaskAgnostic =
false;
2336 State = VTypeState::SeenMaskPolicy;
2349 bool Fractional =
false;
2350 bool TailAgnostic =
false;
2351 bool MaskAgnostic =
false;
2352 bool AltFmt =
false;
2354 VTypeState State = VTypeState::SeenNothingYet;
2356 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2357 MaskAgnostic, AltFmt)) {
2359 if (State == VTypeState::SeenNothingYet)
2368 State == VTypeState::SeenNothingYet)
2369 return generateVTypeError(S);
2373 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2374 unsigned MaxSEW = ELEN / Lmul;
2376 if (MaxSEW >= 8 && Sew > MaxSEW)
2377 Warning(S,
"use of vtype encodings with SEW > " +
Twine(MaxSEW) +
2378 " and LMUL == mf" +
Twine(Lmul) +
2379 " may not be compatible with all RVV implementations");
2384 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2388bool RISCVAsmParser::generateVTypeError(
SMLoc ErrorLoc) {
2389 if (STI->
hasFeature(RISCV::FeatureStdExtZvfbfa))
2393 "e[8|8alt|16|16alt|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2397 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2405 bool AltFmt =
false;
2417 if (Identifier !=
"16alt")
2446 Operands.push_back(RISCVOperand::createVType(
2452 return generateXSfmmVTypeError(S);
2455bool RISCVAsmParser::generateXSfmmVTypeError(
SMLoc ErrorLoc) {
2456 return Error(ErrorLoc,
"operand must be e[8|16|16alt|32|64],w[1|2|4]");
2464 if (!
Name.consume_back(
".t"))
2465 return Error(getLoc(),
"expected '.t' suffix");
2470 if (Reg != RISCV::V0)
2473 SMLoc E = getTok().getEndLoc();
2475 Operands.push_back(RISCVOperand::createReg(Reg, S, E));
2480 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2496 SMLoc E = getTok().getEndLoc();
2498 Operands.push_back(RISCVOperand::createReg(
2499 Reg, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2504 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2516 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(Reg))
2519 if ((Reg - RISCV::X0) & 1) {
2522 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2523 return TokError(
"double precision floating point operands must use even "
2524 "numbered X register");
2529 SMLoc E = getTok().getEndLoc();
2534 Reg, RISCV::sub_gpr_even,
2535 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2536 Operands.push_back(RISCVOperand::createReg(Pair, S, E,
true));
2540template <
bool IsRV64>
2542 return parseGPRPair(
Operands, IsRV64);
2552 if (!IsRV64Inst && isRV64())
2564 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(Reg))
2567 if ((Reg - RISCV::X0) & 1)
2568 return TokError(
"register must be even");
2571 SMLoc E = getTok().getEndLoc();
2576 Reg, RISCV::sub_gpr_even,
2577 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2578 Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2585 "operand must be a valid floating point rounding mode mnemonic");
2587 StringRef Str = getLexer().getTok().getIdentifier();
2592 "operand must be a valid floating point rounding mode mnemonic");
2594 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2600 const AsmToken &Tok = getLexer().getTok();
2606 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2620 for (
char c : Str) {
2649 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2655 return TokError(
"operand must be formed of letters selected in-order from "
2662 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2664 if (!parseRegister(
Operands).isSuccess())
2665 return Error(getLoc(),
"expected register");
2669 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2693 std::unique_ptr<RISCVOperand> OptionalImmOp;
2700 SMLoc ImmStart = getLoc();
2701 if (getParser().parseIntToken(ImmVal,
2702 "expected '(' or optional integer offset"))
2707 SMLoc ImmEnd = getLoc();
2710 ImmStart, ImmEnd, isRV64());
2714 OptionalImmOp ?
"expected '(' after optional integer offset"
2715 :
"expected '(' or optional integer offset"))
2718 if (!parseRegister(
Operands).isSuccess())
2719 return Error(getLoc(),
"expected register");
2725 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2727 OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2728 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2739 StringRef OffsetRegName = getLexer().getTok().getIdentifier();
2742 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(OffsetReg))
2743 return Error(getLoc(),
"expected GPR register");
2750 return Error(getLoc(),
"expected GPR register");
2752 StringRef BaseRegName = getLexer().getTok().getIdentifier();
2755 !RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(BaseReg))
2756 return Error(getLoc(),
"expected GPR register");
2762 Operands.push_back(RISCVOperand::createRegReg(BaseReg, OffsetReg, S));
2775 bool MustIncludeS0) {
2787 return Error(getLoc(),
"invalid register");
2792 return Error(getLoc(),
"invalid register");
2795 UsesXRegs =
RegName[0] ==
'x';
2796 if (Reg != RISCV::X1)
2797 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2798 }
else if (RegEnd == RISCV::X1) {
2799 if (Reg != RISCV::X8 || (UsesXRegs != (
RegName[0] ==
'x')))
2800 return Error(getLoc(),
Twine(
"register must be '") +
2801 (UsesXRegs ?
"x8" :
"s0") +
"'");
2802 }
else if (RegEnd == RISCV::X9 && UsesXRegs) {
2803 if (Reg != RISCV::X18 || (
RegName[0] !=
'x'))
2804 return Error(getLoc(),
"register must be 'x18'");
2806 return Error(getLoc(),
"too many register ranges");
2813 SMLoc MinusLoc = getLoc();
2815 if (RegEnd == RISCV::X1)
2816 return Error(MinusLoc,
Twine(
"register '") + (UsesXRegs ?
"x1" :
"ra") +
2817 "' cannot start a multiple register range");
2820 return Error(getLoc(),
"invalid register");
2825 return Error(getLoc(),
"invalid register");
2827 if (RegEnd == RISCV::X8) {
2828 if ((Reg != RISCV::X9 &&
2829 (UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||
2830 (UsesXRegs != (
RegName[0] ==
'x'))) {
2832 return Error(getLoc(),
"register must be 'x9'");
2833 return Error(getLoc(),
"register must be in the range 's1' to 's11'");
2835 }
else if (RegEnd == RISCV::X18) {
2836 if (Reg < RISCV::X19 || Reg > RISCV::X27 || (
RegName[0] !=
'x'))
2837 return Error(getLoc(),
2838 "register must be in the range 'x19' to 'x27'");
2851 if (RegEnd == RISCV::X26)
2852 return Error(S,
"invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
2853 "x18-x26}' is not supported");
2859 return Error(S,
"register list must include 's0' or 'x8'");
2861 Operands.push_back(RISCVOperand::createRegList(Encode, S));
2867 bool ExpectNegative) {
2876 auto *RegListOp =
static_cast<RISCVOperand *
>(
Operands.back().get());
2877 if (!RegListOp->isRegList())
2880 unsigned RlistEncode = RegListOp->RegList.Encoding;
2884 if (Negative != ExpectNegative || StackAdjustment % 16 != 0 ||
2885 StackAdjustment < StackAdjBase || (StackAdjustment - StackAdjBase) > 48) {
2886 int64_t
Lower = StackAdjBase;
2887 int64_t
Upper = StackAdjBase + 48;
2888 if (ExpectNegative) {
2893 return generateImmOutOfRangeError(S,
Lower,
Upper,
2894 "stack adjustment for register list must "
2895 "be a multiple of 16 bytes in the range");
2899 Operands.push_back(RISCVOperand::createStackAdj(StackAdj, S));
2911 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2918 if (parseRegister(
Operands,
true).isSuccess())
2925 return !parseMemOpBaseReg(
Operands).isSuccess();
2930 Error(getLoc(),
"unknown operand");
2941 const FeatureBitset &AvailableFeatures = getAvailableFeatures();
2945 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2964 if (getParser().parseEOL(
"unexpected token")) {
2965 getParser().eatToEndOfStatement();
2971bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2974 if (
const auto *RE = dyn_cast<MCSpecifierExpr>(Expr)) {
2975 Kind = RE->getSpecifier();
2976 Expr = RE->getSubExpr();
2985bool RISCVAsmParser::isSymbolDiff(
const MCExpr *Expr) {
2997 if (IDVal ==
".option")
2998 return parseDirectiveOption();
2999 if (IDVal ==
".attribute")
3000 return parseDirectiveAttribute();
3001 if (IDVal ==
".insn")
3002 return parseDirectiveInsn(DirectiveID.
getLoc());
3003 if (IDVal ==
".variant_cc")
3004 return parseDirectiveVariantCC();
3009bool RISCVAsmParser::resetToArch(
StringRef Arch,
SMLoc Loc, std::string &Result,
3010 bool FromOptionDirective) {
3013 clearFeatureBits(Feature.Value, Feature.Key);
3022 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
3023 << ErrMsg.getMessage();
3026 return Error(Loc, OutputErrMsg.str());
3031 if (ISAInfo->hasExtension(Feature.Key))
3032 setFeatureBits(Feature.Value, Feature.Key);
3034 if (FromOptionDirective) {
3035 if (ISAInfo->getXLen() == 32 && isRV64())
3036 return Error(Loc,
"bad arch string switching from rv64 to rv32");
3037 else if (ISAInfo->getXLen() == 64 && !isRV64())
3038 return Error(Loc,
"bad arch string switching from rv32 to rv64");
3041 if (ISAInfo->getXLen() == 32)
3042 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
3043 else if (ISAInfo->getXLen() == 64)
3044 setFeatureBits(RISCV::Feature64Bit,
"64bit");
3046 return Error(Loc,
"bad arch string " + Arch);
3048 Result = ISAInfo->toString();
3052bool RISCVAsmParser::parseDirectiveOption() {
3063 if (Option ==
"push") {
3067 getTargetStreamer().emitDirectiveOptionPush();
3072 if (Option ==
"pop") {
3077 getTargetStreamer().emitDirectiveOptionPop();
3078 if (popFeatureBits())
3079 return Error(StartLoc,
".option pop with no .option push");
3084 if (Option ==
"arch") {
3092 Type = RISCVOptionArchArgType::Plus;
3094 Type = RISCVOptionArchArgType::Minus;
3095 else if (!
Args.empty())
3097 "unexpected token, expected + or -");
3099 Type = RISCVOptionArchArgType::Full;
3103 "unexpected token, expected identifier");
3109 if (
Type == RISCVOptionArchArgType::Full) {
3111 if (resetToArch(Arch, Loc, Result,
true))
3120 Loc,
"extension version number parsing not currently implemented");
3123 if (!enableExperimentalExtension() &&
3125 return Error(Loc,
"unexpected experimental extensions");
3128 return Error(Loc,
"unknown extension feature");
3132 if (
Type == RISCVOptionArchArgType::Plus) {
3135 setFeatureBits(
Ext->Value,
Ext->Key);
3138 copySTI().setFeatureBits(OldFeatureBits);
3139 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3144 OutputErrMsg << ErrMsg.getMessage();
3147 return Error(Loc, OutputErrMsg.str());
3150 assert(
Type == RISCVOptionArchArgType::Minus);
3155 if (getSTI().hasFeature(Feature.Value) &&
3156 Feature.Implies.test(
Ext->Value))
3158 " extension; " + Feature.Key +
3159 " extension requires " +
Ext->Key +
3163 clearFeatureBits(
Ext->Value,
Ext->Key);
3170 getTargetStreamer().emitDirectiveOptionArch(Args);
3174 if (Option ==
"exact") {
3178 getTargetStreamer().emitDirectiveOptionExact();
3179 setFeatureBits(RISCV::FeatureExactAssembly,
"exact-asm");
3180 clearFeatureBits(RISCV::FeatureRelax,
"relax");
3184 if (Option ==
"noexact") {
3188 getTargetStreamer().emitDirectiveOptionNoExact();
3189 clearFeatureBits(RISCV::FeatureExactAssembly,
"exact-asm");
3190 setFeatureBits(RISCV::FeatureRelax,
"relax");
3194 if (Option ==
"rvc") {
3198 getTargetStreamer().emitDirectiveOptionRVC();
3199 setFeatureBits(RISCV::FeatureStdExtC,
"c");
3203 if (Option ==
"norvc") {
3207 getTargetStreamer().emitDirectiveOptionNoRVC();
3208 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
3209 clearFeatureBits(RISCV::FeatureStdExtZca,
"zca");
3213 if (Option ==
"pic") {
3217 getTargetStreamer().emitDirectiveOptionPIC();
3218 ParserOptions.IsPicEnabled =
true;
3222 if (Option ==
"nopic") {
3226 getTargetStreamer().emitDirectiveOptionNoPIC();
3227 ParserOptions.IsPicEnabled =
false;
3231 if (Option ==
"relax") {
3235 getTargetStreamer().emitDirectiveOptionRelax();
3236 setFeatureBits(RISCV::FeatureRelax,
"relax");
3240 if (Option ==
"norelax") {
3244 getTargetStreamer().emitDirectiveOptionNoRelax();
3245 clearFeatureBits(RISCV::FeatureRelax,
"relax");
3251 "unknown option, expected 'push', 'pop', "
3252 "'rvc', 'norvc', 'arch', 'relax', 'norelax', "
3253 "'exact', or 'noexact'");
3261bool RISCVAsmParser::parseDirectiveAttribute() {
3268 std::optional<unsigned>
Ret =
3271 return Error(TagLoc,
"attribute name not recognised: " +
Name);
3282 if (check(!CE, TagLoc,
"expected numeric constant"))
3285 Tag =
CE->getValue();
3292 int64_t IntegerValue = 0;
3293 bool IsIntegerValue =
true;
3298 IsIntegerValue =
false;
3301 if (IsIntegerValue) {
3308 return Error(ValueExprLoc,
"expected numeric constant");
3309 IntegerValue =
CE->getValue();
3322 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3324 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3327 if (resetToArch(StringValue, ValueExprLoc, Result,
false))
3331 getTargetStreamer().emitTextAttribute(Tag, Result);
3339 .
Cases(
"r",
"r4",
"i",
"b",
"sb",
"u",
"j",
"uj",
"s",
true)
3340 .
Cases(
"cr",
"ci",
"ciw",
"css",
"cl",
"cs",
"ca",
"cb",
"cj",
3342 .
Cases(
"qc.eai",
"qc.ei",
"qc.eb",
"qc.ej",
"qc.es",
3351bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
3359 std::optional<int64_t>
Length;
3369 return Error(ErrorLoc,
3370 "instruction lengths must be a non-zero multiple of two");
3374 return Error(ErrorLoc,
3375 "instruction lengths over 64 bits are not supported");
3381 int64_t EncodingDerivedLength = ((
Value & 0b11) == 0b11) ? 4 : 2;
3386 if ((*
Length <= 4) && (*
Length != EncodingDerivedLength))
3387 return Error(ErrorLoc,
3388 "instruction length does not match the encoding");
3391 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3394 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3397 if (!getSTI().hasFeature(RISCV::FeatureStdExtZca) &&
3398 (EncodingDerivedLength == 2))
3399 return Error(ErrorLoc,
"compressed instructions are not allowed");
3401 if (getParser().parseEOL(
"invalid operand for instruction")) {
3402 getParser().eatToEndOfStatement();
3410 Opcode = RISCV::Insn16;
3413 Opcode = RISCV::Insn32;
3416 Opcode = RISCV::Insn48;
3419 Opcode = RISCV::Insn64;
3425 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3432 return Error(ErrorLoc,
"invalid instruction format");
3434 std::string FormatName = (
".insn_" +
Format).str();
3439 if (parseInstruction(Info, FormatName, L,
Operands))
3451bool RISCVAsmParser::parseDirectiveVariantCC() {
3453 if (getParser().parseIdentifier(
Name))
3454 return TokError(
"expected symbol name");
3457 getTargetStreamer().emitDirectiveVariantCC(
3458 *getContext().getOrCreateSymbol(
Name));
3466 if (!STI.
hasFeature(RISCV::FeatureExactAssembly))
3469 ++RISCVNumInstrsCompressed;
3478 for (
MCInst &Inst : Seq) {
3479 emitToStreamer(Out, Inst);
3486 unsigned SecondOpcode,
SMLoc IDLoc,
3498 MCInstBuilder(RISCV::AUIPC).addReg(TmpReg).addExpr(SymbolHi));
3506 .addExpr(RefToLinkTmpLabel));
3509void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
3519 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_PCREL_HI20,
3520 RISCV::ADDI, IDLoc, Out);
3523void RISCVAsmParser::emitLoadGlobalAddress(
MCInst &Inst,
SMLoc IDLoc,
3533 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3534 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_GOT_HI20,
3535 SecondOpcode, IDLoc, Out);
3538void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
3547 if (ParserOptions.IsPicEnabled)
3548 emitLoadGlobalAddress(Inst, IDLoc, Out);
3550 emitLoadLocalAddress(Inst, IDLoc, Out);
3553void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
3563 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3564 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GOT_HI20,
3565 SecondOpcode, IDLoc, Out);
3568void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
3578 emitAuipcInstPair(DestReg, DestReg, Symbol, ELF::R_RISCV_TLS_GD_HI20,
3579 RISCV::ADDI, IDLoc, Out);
3582void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
3592 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3594 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3598 if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].
contains(TmpReg)) {
3600 TmpReg = RI->
getSubReg(TmpReg, RISCV::sub_gpr_even);
3604 emitAuipcInstPair(DestReg, TmpReg, Symbol, ELF::R_RISCV_PCREL_HI20, Opcode,
3608void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
3609 int64_t Width,
SMLoc IDLoc,
3621 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3622 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3624 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
3637void RISCVAsmParser::emitVMSGE(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
3661 "The destination register should not be V0.");
3680 "The destination register should be V0.");
3682 "The temporary vector register should not be V0.");
3701 "The temporary vector register should not be V0.");
3726bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
3728 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
3731 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3732 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
3733 "%tprel_add specifier");
3739bool RISCVAsmParser::checkPseudoTLSDESCCall(
MCInst &Inst,
3741 assert(Inst.
getOpcode() == RISCV::PseudoTLSDESCCall &&
"Invalid instruction");
3744 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3745 return Error(ErrorLoc,
"the output operand must be t0/x5 when using "
3746 "%tlsdesc_call specifier");
3752std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
3756std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
3757 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3761std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp()
const {
3762 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3766bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
3770 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3771 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3774 if (DestReg == TempReg) {
3776 return Error(Loc,
"the temporary vector register cannot be the same as "
3777 "the destination register");
3781 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3782 Opcode == RISCV::TH_LWD) {
3787 if (Rs1 == Rd1 || Rs1 == Rd2 || Rd1 == Rd2) {
3789 return Error(Loc,
"rs1, rd1, and rd2 cannot overlap");
3793 if (Opcode == RISCV::CM_MVSA01 || Opcode == RISCV::QC_CM_MVSA01) {
3798 return Error(Loc,
"rs1 and rs2 must be different");
3806 if (Opcode == RISCV::SF_VC_V_XVW || Opcode == RISCV::SF_VC_V_IVW ||
3807 Opcode == RISCV::SF_VC_V_FVW || Opcode == RISCV::SF_VC_V_VVW) {
3813 if (VCIXDst == VCIXRs1)
3814 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3815 " overlap the source vector register group");
3819 if (VCIXDst == VCIXRs2)
3820 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3821 " overlap the source vector register group");
3836 if (DestReg == CheckReg)
3837 return Error(Loc,
"the destination vector register group cannot overlap"
3838 " the source vector register group");
3842 if (DestReg == CheckReg)
3843 return Error(Loc,
"the destination vector register group cannot overlap"
3844 " the source vector register group");
3849 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3850 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3851 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3852 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3853 Opcode == RISCV::VMERGE_VXM)
3854 return Error(Loc,
"the destination vector register group cannot be V0");
3861 assert((CheckReg == RISCV::V0 || !CheckReg) &&
3862 "Unexpected register for mask operand");
3864 if (DestReg == CheckReg)
3865 return Error(Loc,
"the destination vector register group cannot overlap"
3866 " the mask register");
3871bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
3879 case RISCV::PseudoC_ADDI_NOP: {
3887 case RISCV::PseudoLLAImm:
3888 case RISCV::PseudoLAImm:
3889 case RISCV::PseudoLI: {
3906 Imm = SignExtend64<32>(Imm);
3907 emitLoadImm(Reg, Imm, Out);
3910 case RISCV::PseudoLLA:
3911 emitLoadLocalAddress(Inst, IDLoc, Out);
3913 case RISCV::PseudoLGA:
3914 emitLoadGlobalAddress(Inst, IDLoc, Out);
3916 case RISCV::PseudoLA:
3917 emitLoadAddress(Inst, IDLoc, Out);
3919 case RISCV::PseudoLA_TLS_IE:
3920 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3922 case RISCV::PseudoLA_TLS_GD:
3923 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3925 case RISCV::PseudoLB:
3926 case RISCV::PseudoQC_E_LB:
3927 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
3929 case RISCV::PseudoLBU:
3930 case RISCV::PseudoQC_E_LBU:
3931 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
3933 case RISCV::PseudoLH:
3934 case RISCV::PseudoQC_E_LH:
3935 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
3937 case RISCV::PseudoLHU:
3938 case RISCV::PseudoQC_E_LHU:
3939 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
3941 case RISCV::PseudoLW:
3942 case RISCV::PseudoQC_E_LW:
3943 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
3945 case RISCV::PseudoLWU:
3946 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
3948 case RISCV::PseudoLD:
3949 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
3951 case RISCV::PseudoLD_RV32:
3952 emitLoadStoreSymbol(Inst, RISCV::LD_RV32, IDLoc, Out,
false);
3954 case RISCV::PseudoFLH:
3955 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
3957 case RISCV::PseudoFLW:
3958 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
3960 case RISCV::PseudoFLD:
3961 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
3963 case RISCV::PseudoFLQ:
3964 emitLoadStoreSymbol(Inst, RISCV::FLQ, IDLoc, Out,
true);
3966 case RISCV::PseudoSB:
3967 case RISCV::PseudoQC_E_SB:
3968 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
3970 case RISCV::PseudoSH:
3971 case RISCV::PseudoQC_E_SH:
3972 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
3974 case RISCV::PseudoSW:
3975 case RISCV::PseudoQC_E_SW:
3976 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
3978 case RISCV::PseudoSD:
3979 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
3981 case RISCV::PseudoSD_RV32:
3982 emitLoadStoreSymbol(Inst, RISCV::SD_RV32, IDLoc, Out,
true);
3984 case RISCV::PseudoFSH:
3985 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
3987 case RISCV::PseudoFSW:
3988 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
3990 case RISCV::PseudoFSD:
3991 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
3993 case RISCV::PseudoFSQ:
3994 emitLoadStoreSymbol(Inst, RISCV::FSQ, IDLoc, Out,
true);
3996 case RISCV::PseudoAddTPRel:
3997 if (checkPseudoAddTPRel(Inst,
Operands))
4000 case RISCV::PseudoTLSDESCCall:
4001 if (checkPseudoTLSDESCCall(Inst,
Operands))
4004 case RISCV::PseudoSEXT_B:
4005 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
4007 case RISCV::PseudoSEXT_H:
4008 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
4010 case RISCV::PseudoZEXT_H:
4011 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
4013 case RISCV::PseudoZEXT_W:
4014 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
4016 case RISCV::PseudoVMSGEU_VX:
4017 case RISCV::PseudoVMSGEU_VX_M:
4018 case RISCV::PseudoVMSGEU_VX_M_T:
4019 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
4021 case RISCV::PseudoVMSGE_VX:
4022 case RISCV::PseudoVMSGE_VX_M:
4023 case RISCV::PseudoVMSGE_VX_M_T:
4024 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
4026 case RISCV::PseudoVMSGE_VI:
4027 case RISCV::PseudoVMSLT_VI: {
4031 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
4041 case RISCV::PseudoVMSGEU_VI:
4042 case RISCV::PseudoVMSLTU_VI: {
4049 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
4060 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
4075 emitToStreamer(Out, Inst);
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID)
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
static bool matchRegisterNameHelper(const MCSubtargetInfo &STI, MCRegister &Reg, StringRef Name)
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
#define LLVM_EXTERNAL_VISIBILITY
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
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
mir Rename Register Operands
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")
bool isValidInsnFormat(StringRef Format, const MCSubtargetInfo &STI)
static MCRegister convertFPR64ToFPR128(MCRegister Reg)
static MCRegister convertFPR64ToFPR32(MCRegister Reg)
static cl::opt< bool > AddBuildAttributes("riscv-add-build-attributes", cl::init(false))
static MCRegister convertFPR64ToFPR16(MCRegister Reg)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser()
static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg, unsigned Kind)
static bool isDigit(const char C)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
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)
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
Class for arbitrary precision integers.
Target independent representation for an assembler token.
LLVM_ABI SMLoc getLoc() const
int64_t getIntVal() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class represents an Operation in the Expression.
Encoding
Size and signedness of expression operations' operands.
Base class for user error types.
Lightweight error class with error context and mandatory checking.
Container class for subtarget features.
constexpr size_t size() const
This class is intended to be used as a base class for asm properties and features specific to the tar...
void printExpr(raw_ostream &, const MCExpr &) const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
MCStreamer & getStreamer()
MCAsmParser & getParser()
Generic assembler parser interface, for use by target specific assembly parsers.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
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.
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.
MCStreamer & getStreamer()
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
const MCObjectFileInfo * getObjectFileInfo() const
LLVM_ABI MCSymbol * createNamedTempSymbol()
Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getOpcode() const
void addOperand(const MCOperand Op)
const MCOperand & getOperand(unsigned i) const
Describe properties that are true of each instruction in the target description file.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
bool isPositionIndependent() const
Instances of this class represent operands of the MCInst class.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
MCRegister getReg() const
Returns the register number.
const MCExpr * getExpr() const
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.
MCRegister getSubReg(MCRegister Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo.
Wrapper class representing physical registers. Should be passed by value.
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
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.
MCTargetStreamer * getTargetStreamer()
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, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
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.
@ FIRST_TARGET_MATCH_RESULT_TY
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
virtual bool parseDataExpr(const MCExpr *&Res)
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.
const MCSymbol * getAddSym() const
uint32_t getSpecifier() const
const MCSymbol * getSubSym() const
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 LLVM_ABI bool isSupportedExtensionFeature(StringRef Ext)
static LLVM_ABI std::string getTargetFeatureForExtension(StringRef Ext)
static LLVM_ABI 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)
Wrapper class representing virtual and physical registers.
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
Represents a range in source code.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class wraps a string in an Error.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
char back() const
back - Get the last character in the string.
A switch()-like statement whose cases are string literals.
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#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.
LLVM_ABI std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, StringRef ABIName)
LLVM_ABI 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 VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
LLVM_ABI unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt)
static bool isValidLMUL(unsigned LMUL, bool Fractional)
static bool isValidSEW(unsigned SEW)
LLVM_ABI void printVType(unsigned VType, raw_ostream &OS)
static bool isValidXSfmmVType(unsigned VTypeI)
LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic, bool AltFmt=false)
unsigned encodeRegList(MCRegister EndReg, bool IsRVE=false)
static unsigned getStackAdjBase(unsigned RlistVal, bool IsRV64)
void printRegList(unsigned RlistEncode, raw_ostream &OS)
Specifier parseSpecifierName(StringRef name)
@ 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)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
static bool isMem(const MachineInstr &MI, unsigned Op)
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
testing::Matcher< const detail::ErrorHolder & > Failed()
Target & getTheRISCV32Target()
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Target & getTheRISCV64beTarget()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI 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...
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.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]
Target & getTheRISCV32beTarget()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
Used to provide key value pairs for feature and CPU bit flags.