48#define DEBUG_TYPE "riscv-asm-parser"
51 "Number of RISC-V Compressed instructions emitted");
63struct ParserOptionsSet {
75 VTypeState_TailPolicy,
76 VTypeState_MaskPolicy,
83 ParserOptionsSet ParserOptions;
88 bool enableExperimentalExtension()
const {
94 "do not have a target streamer");
100 unsigned Kind)
override;
105 bool generateImmOutOfRangeError(
SMLoc ErrorLoc, int64_t
Lower, int64_t
Upper,
111 bool MatchingInlineAsm)
override;
116 SMLoc &EndLoc)
override;
123 bool parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
unsigned &Sew,
124 unsigned &Lmul,
bool &Fractional,
bool &TailAgnostic,
126 bool generateVTypeError(
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"
222 bool ExpectNegative =
false);
224 return parseZcmpStackAdj(
Operands,
true);
229 bool parseDirectiveOption();
230 bool parseDirectiveAttribute();
231 bool parseDirectiveInsn(
SMLoc L);
232 bool parseDirectiveVariantCC();
238 bool FromOptionDirective);
241 if (!(
getSTI().hasFeature(Feature))) {
249 if (
getSTI().hasFeature(Feature)) {
256 void pushFeatureBits() {
258 "These two stacks must be kept synchronized");
260 ParserOptionsStack.
push_back(ParserOptions);
263 bool popFeatureBits() {
265 "These two stacks must be kept synchronized");
266 if (FeatureBitStack.
empty())
278 std::unique_ptr<RISCVOperand> defaultMaskRegOp()
const;
279 std::unique_ptr<RISCVOperand> defaultFRMArgOp()
const;
280 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp()
const;
283 enum RISCVMatchResultTy {
285#define GET_OPERAND_DIAGNOSTIC_TYPES
286#include "RISCVGenAsmMatcher.inc"
287#undef GET_OPERAND_DIAGNOSTIC_TYPES
290 static bool classifySymbolRef(
const MCExpr *Expr,
292 static bool isSymbolDiff(
const MCExpr *Expr);
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 "
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 "
326 getTargetStreamer().emitTargetAttributes(STI,
false);
395 SMLoc StartLoc, EndLoc;
401 struct SysRegOp SysReg;
402 struct VTypeOp VType;
404 struct FenceOp Fence;
405 struct RlistOp Rlist;
406 struct SpimmOp Spimm;
410 RISCVOperand(KindTy K) :
Kind(
K) {}
415 StartLoc =
o.StartLoc;
418 case KindTy::Register:
421 case KindTy::Immediate:
424 case KindTy::FPImmediate:
430 case KindTy::SystemRegister:
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;
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));
465 bool isAnyRegC()
const {
466 return Kind == KindTy::Register &&
467 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
469 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
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; }
480 return Kind == KindTy::Register &&
481 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum);
484 bool isGPRPair()
const {
485 return Kind == KindTy::Register &&
486 RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
490 bool isGPRF16()
const {
491 return Kind == KindTy::Register &&
492 RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(
Reg.RegNum);
495 bool isGPRF32()
const {
496 return Kind == KindTy::Register &&
497 RISCVMCRegisterClasses[RISCV::GPRF32RegClassID].contains(
Reg.RegNum);
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; }
505 static bool evaluateConstantImm(
const MCExpr *Expr, int64_t &Imm,
507 if (
auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
509 return RE->evaluateAsConstant(Imm);
512 if (
auto CE = dyn_cast<MCConstantExpr>(Expr)) {
514 Imm =
CE->getValue();
523 template <
int N>
bool isBareSimmNLsb0()
const {
528 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
531 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
533 IsValid =
isShiftedInt<
N - 1, 1>(fixImmediateForRV32(Imm, isRV64Imm()));
539 bool isBareSymbol()
const {
543 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
545 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
549 bool isCallSymbol()
const {
553 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
555 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
560 bool isPseudoJumpSymbol()
const {
564 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
566 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
570 bool isTPRelAddSymbol()
const {
574 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
576 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
580 bool isTLSDESCCallSymbol()
const {
584 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
586 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
590 bool isCSRSystemRegister()
const {
return isSystemRegister(); }
592 bool isVTypeImm(
unsigned N)
const {
597 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
603 bool isVTypeI10()
const {
604 if (Kind == KindTy::Immediate)
605 return isVTypeImm(10);
606 return Kind == KindTy::VType;
608 bool isVTypeI11()
const {
609 if (Kind == KindTy::Immediate)
610 return isVTypeImm(11);
611 return Kind == KindTy::VType;
616 bool isFenceArg()
const {
return Kind == KindTy::Fence; }
619 bool isFRMArg()
const {
return Kind == KindTy::FRM; }
620 bool isFRMArgLegacy()
const {
return Kind == KindTy::FRM; }
624 bool isLoadFPImm()
const {
627 if (Kind != KindTy::FPImmediate)
630 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
633 return Idx >= 0 &&
Idx != 1;
636 bool isImmXLenLI()
const {
641 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
651 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
654 return RISCVAsmParser::isSymbolDiff(getImm());
657 bool isImmXLenLI_Restricted()
const {
662 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
665 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
668 bool isUImmLog2XLen()
const {
673 if (!evaluateConstantImm(getImm(), Imm, VK) ||
676 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
679 bool isUImmLog2XLenNonZero()
const {
684 if (!evaluateConstantImm(getImm(), Imm, VK) ||
689 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
692 bool isUImmLog2XLenHalf()
const {
697 if (!evaluateConstantImm(getImm(), Imm, VK) ||
700 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
703 template <
unsigned N>
bool IsUImm()
const {
708 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
712 bool isUImm1()
const {
return IsUImm<1>(); }
713 bool isUImm2()
const {
return IsUImm<2>(); }
714 bool isUImm3()
const {
return IsUImm<3>(); }
715 bool isUImm4()
const {
return IsUImm<4>(); }
716 bool isUImm5()
const {
return IsUImm<5>(); }
717 bool isUImm6()
const {
return IsUImm<6>(); }
718 bool isUImm7()
const {
return IsUImm<7>(); }
719 bool isUImm8()
const {
return IsUImm<8>(); }
720 bool isUImm11()
const {
return IsUImm<11>(); }
721 bool isUImm16()
const {
return IsUImm<16>(); }
722 bool isUImm20()
const {
return IsUImm<20>(); }
723 bool isUImm32()
const {
return IsUImm<32>(); }
724 bool isUImm48()
const {
return IsUImm<48>(); }
725 bool isUImm64()
const {
return IsUImm<64>(); }
727 bool isUImm5NonZero()
const {
732 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
733 return IsConstantImm && isUInt<5>(Imm) && (
Imm != 0) &&
737 bool isUImm5GT3()
const {
742 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
743 return IsConstantImm && isUInt<5>(Imm) && (
Imm > 3) &&
747 bool isUImm8GE32()
const {
752 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
753 return IsConstantImm && isUInt<8>(Imm) &&
Imm >= 32 &&
757 bool isRnumArg()
const {
762 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
763 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(10) &&
767 bool isRnumArg_0_7()
const {
772 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
773 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(7) &&
777 bool isRnumArg_1_10()
const {
782 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
783 return IsConstantImm &&
Imm >= INT64_C(1) &&
Imm <= INT64_C(10) &&
787 bool isRnumArg_2_14()
const {
792 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
793 return IsConstantImm &&
Imm >= INT64_C(2) &&
Imm <= INT64_C(14) &&
797 bool isSImm5()
const {
802 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
803 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
807 bool isSImm6()
const {
812 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
813 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
817 bool isSImm6NonZero()
const {
822 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
823 return IsConstantImm &&
Imm != 0 &&
824 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
828 bool isCLUIImm()
const {
833 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
834 return IsConstantImm && (
Imm != 0) &&
835 (isUInt<5>(Imm) || (
Imm >= 0xfffe0 &&
Imm <= 0xfffff)) &&
839 bool isUImm2Lsb0()
const {
844 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
845 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
849 bool isUImm5Lsb0()
const {
854 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
855 return IsConstantImm && isShiftedUInt<4, 1>(Imm) &&
859 bool isUImm6Lsb0()
const {
864 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
865 return IsConstantImm && isShiftedUInt<5, 1>(Imm) &&
869 bool isUImm7Lsb00()
const {
874 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
875 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
879 bool isUImm8Lsb00()
const {
884 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
885 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
889 bool isUImm8Lsb000()
const {
894 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
895 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
899 bool isSImm9Lsb0()
const {
return isBareSimmNLsb0<9>(); }
901 bool isUImm9Lsb000()
const {
906 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
907 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
911 bool isUImm10Lsb00NonZero()
const {
916 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
917 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (
Imm != 0) &&
923 static int64_t fixImmediateForRV32(int64_t Imm,
bool IsRV64Imm) {
924 if (IsRV64Imm || !isUInt<32>(Imm))
926 return SignExtend64<32>(Imm);
929 bool isSImm12()
const {
935 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
937 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
939 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
948 bool isSImm12Lsb0()
const {
return isBareSimmNLsb0<12>(); }
950 bool isSImm12Lsb00000()
const {
955 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
956 return IsConstantImm &&
957 isShiftedInt<7, 5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
961 bool isSImm13Lsb0()
const {
return isBareSimmNLsb0<13>(); }
963 bool isSImm10Lsb0000NonZero()
const {
968 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
969 return IsConstantImm && (
Imm != 0) &&
970 isShiftedInt<6, 4>(fixImmediateForRV32(Imm, isRV64Imm())) &&
974 bool isUImm20LUI()
const {
980 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
981 if (!IsConstantImm) {
982 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
992 bool isUImm20AUIPC()
const {
998 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
999 if (!IsConstantImm) {
1000 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
1016 bool isSImm21Lsb0JAL()
const {
return isBareSimmNLsb0<21>(); }
1018 bool isImmZero()
const {
1023 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1027 bool isSImm5Plus1()
const {
1032 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1033 return IsConstantImm &&
1034 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
1039 SMLoc getStartLoc()
const override {
return StartLoc; }
1041 SMLoc getEndLoc()
const override {
return EndLoc; }
1043 bool isRV64Imm()
const {
1044 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1049 assert(Kind == KindTy::Register &&
"Invalid type access!");
1054 assert(Kind == KindTy::SystemRegister &&
"Invalid type access!");
1055 return StringRef(SysReg.Data, SysReg.Length);
1058 const MCExpr *getImm()
const {
1059 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1064 assert(Kind == KindTy::FPImmediate &&
"Invalid type access!");
1069 assert(Kind == KindTy::Token &&
"Invalid type access!");
1073 unsigned getVType()
const {
1074 assert(Kind == KindTy::VType &&
"Invalid type access!");
1079 assert(Kind == KindTy::FRM &&
"Invalid type access!");
1083 unsigned getFence()
const {
1084 assert(Kind == KindTy::Fence &&
"Invalid type access!");
1097 case KindTy::Immediate:
1100 case KindTy::FPImmediate:
1102 case KindTy::Register:
1106 OS <<
"'" << getToken() <<
"'";
1108 case KindTy::SystemRegister:
1109 OS <<
"<sysreg: " << getSysReg() <<
'>';
1118 roundingModeToString(getFRM());
1136 case KindTy::RegReg:
1143 static std::unique_ptr<RISCVOperand> createToken(
StringRef Str,
SMLoc S) {
1144 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1151 static std::unique_ptr<RISCVOperand>
1153 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1154 Op->Reg.RegNum =
Reg.id();
1155 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1161 static std::unique_ptr<RISCVOperand> createImm(
const MCExpr *Val,
SMLoc S,
1163 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1165 Op->Imm.IsRV64 = IsRV64;
1171 static std::unique_ptr<RISCVOperand> createFPImm(
uint64_t Val,
SMLoc S) {
1172 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1173 Op->FPImm.Val = Val;
1179 static std::unique_ptr<RISCVOperand> createSysReg(
StringRef Str,
SMLoc S,
1180 unsigned Encoding) {
1181 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1182 Op->SysReg.Data = Str.data();
1183 Op->SysReg.Length = Str.size();
1190 static std::unique_ptr<RISCVOperand>
1192 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1199 static std::unique_ptr<RISCVOperand> createFenceArg(
unsigned Val,
SMLoc S) {
1200 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1201 Op->Fence.Val = Val;
1207 static std::unique_ptr<RISCVOperand> createVType(
unsigned VTypeI,
SMLoc S) {
1208 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1209 Op->VType.Val = VTypeI;
1215 static std::unique_ptr<RISCVOperand> createRlist(
unsigned RlistEncode,
1217 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1218 Op->Rlist.Val = RlistEncode;
1223 static std::unique_ptr<RISCVOperand> createRegReg(
MCRegister Reg1,
1225 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1226 Op->RegReg.Reg1 = Reg1.
id();
1227 Op->RegReg.Reg2 = Reg2.
id();
1233 static std::unique_ptr<RISCVOperand> createSpimm(
unsigned Spimm,
SMLoc S) {
1234 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1235 Op->Spimm.Val = Spimm;
1240 static void addExpr(
MCInst &Inst,
const MCExpr *Expr,
bool IsRV64Imm) {
1241 assert(Expr &&
"Expr shouldn't be null!");
1244 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1254 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
1255 assert(
N == 1 &&
"Invalid number of operands!");
1259 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
1260 assert(
N == 1 &&
"Invalid number of operands!");
1261 addExpr(Inst, getImm(), isRV64Imm());
1264 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
1265 assert(
N == 1 &&
"Invalid number of operands!");
1267 addExpr(Inst, getImm(), isRV64Imm());
1272 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
1276 void addFenceArgOperands(
MCInst &Inst,
unsigned N)
const {
1277 assert(
N == 1 &&
"Invalid number of operands!");
1281 void addCSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
1282 assert(
N == 1 &&
"Invalid number of operands!");
1289 void addVTypeIOperands(
MCInst &Inst,
unsigned N)
const {
1290 assert(
N == 1 &&
"Invalid number of operands!");
1292 if (Kind == KindTy::Immediate) {
1294 [[maybe_unused]]
bool IsConstantImm =
1295 evaluateConstantImm(getImm(), Imm, VK);
1296 assert(IsConstantImm &&
"Invalid VTypeI Operand!");
1303 void addRlistOperands(
MCInst &Inst,
unsigned N)
const {
1304 assert(
N == 1 &&
"Invalid number of operands!");
1308 void addRegRegOperands(
MCInst &Inst,
unsigned N)
const {
1309 assert(
N == 2 &&
"Invalid number of operands!");
1314 void addSpimmOperands(
MCInst &Inst,
unsigned N)
const {
1315 assert(
N == 1 &&
"Invalid number of operands!");
1319 void addFRMArgOperands(
MCInst &Inst,
unsigned N)
const {
1320 assert(
N == 1 &&
"Invalid number of operands!");
1326#define GET_REGISTER_MATCHER
1327#define GET_SUBTARGET_FEATURE_NAME
1328#define GET_MATCHER_IMPLEMENTATION
1329#define GET_MNEMONIC_SPELL_CHECKER
1330#include "RISCVGenAsmMatcher.inc"
1333 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1334 return Reg - RISCV::F0_D + RISCV::F0_H;
1338 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1339 return Reg - RISCV::F0_D + RISCV::F0_F;
1344 unsigned RegClassID;
1345 if (Kind == MCK_VRM2)
1346 RegClassID = RISCV::VRM2RegClassID;
1347 else if (Kind == MCK_VRM4)
1348 RegClassID = RISCV::VRM4RegClassID;
1349 else if (Kind == MCK_VRM8)
1350 RegClassID = RISCV::VRM8RegClassID;
1354 &RISCVMCRegisterClasses[RegClassID]);
1359 RISCVOperand &
Op =
static_cast<RISCVOperand &
>(AsmOp);
1361 return Match_InvalidOperand;
1365 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg);
1367 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
Reg);
1368 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg);
1372 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1373 (IsRegFPR64C &&
Kind == MCK_FPR32C)) {
1375 return Match_Success;
1379 if (IsRegFPR64 && Kind == MCK_FPR16) {
1381 return Match_Success;
1383 if (Kind == MCK_GPRAsFPR16 &&
Op.isGPRAsFPR()) {
1384 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_H;
1385 return Match_Success;
1387 if (Kind == MCK_GPRAsFPR32 &&
Op.isGPRAsFPR()) {
1388 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_W;
1389 return Match_Success;
1396 if (RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg) &&
1397 Kind == MCK_GPRF64AsFPR && STI->
hasFeature(RISCV::FeatureStdExtZdinx) &&
1399 return Match_Success;
1403 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1406 return Match_InvalidOperand;
1407 return Match_Success;
1409 return Match_InvalidOperand;
1412bool RISCVAsmParser::generateImmOutOfRangeError(
1414 const Twine &Msg =
"immediate must be an integer in the range") {
1418bool RISCVAsmParser::generateImmOutOfRangeError(
1420 const Twine &Msg =
"immediate must be an integer in the range") {
1422 return generateImmOutOfRangeError(ErrorLoc,
Lower,
Upper, Msg);
1425bool RISCVAsmParser::matchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1429 bool MatchingInlineAsm) {
1439 if (validateInstruction(Inst,
Operands))
1441 return processInstruction(Inst, IDLoc,
Operands, Out);
1442 case Match_MissingFeature: {
1443 assert(MissingFeatures.
any() &&
"Unknown missing features!");
1444 bool FirstFeature =
true;
1445 std::string Msg =
"instruction requires the following:";
1446 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
1447 if (MissingFeatures[i]) {
1448 Msg += FirstFeature ?
" " :
", ";
1450 FirstFeature =
false;
1453 return Error(IDLoc, Msg);
1455 case Match_MnemonicFail: {
1456 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1457 std::string Suggestion = RISCVMnemonicSpellCheck(
1458 ((RISCVOperand &)*
Operands[0]).getToken(), FBS, 0);
1459 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
1461 case Match_InvalidOperand: {
1462 SMLoc ErrorLoc = IDLoc;
1465 return Error(ErrorLoc,
"too few operands for instruction");
1468 if (ErrorLoc ==
SMLoc())
1471 return Error(ErrorLoc,
"invalid operand for instruction");
1478 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1479 SMLoc ErrorLoc = IDLoc;
1481 return Error(ErrorLoc,
"too few operands for instruction");
1487 case Match_InvalidImmXLenLI:
1490 return Error(ErrorLoc,
"operand must be a constant 64-bit integer");
1493 std::numeric_limits<int32_t>::min(),
1494 std::numeric_limits<uint32_t>::max());
1495 case Match_InvalidImmXLenLI_Restricted:
1498 return Error(ErrorLoc,
"operand either must be a constant 64-bit integer "
1499 "or a bare symbol name");
1501 return generateImmOutOfRangeError(
1503 std::numeric_limits<uint32_t>::max(),
1504 "operand either must be a bare symbol name or an immediate integer in "
1506 case Match_InvalidImmZero: {
1508 return Error(ErrorLoc,
"immediate must be zero");
1510 case Match_InvalidUImmLog2XLen:
1514 case Match_InvalidUImmLog2XLenNonZero:
1518 case Match_InvalidUImm1:
1520 case Match_InvalidUImm2:
1522 case Match_InvalidUImm2Lsb0:
1524 "immediate must be one of");
1525 case Match_InvalidUImm3:
1527 case Match_InvalidUImm4:
1529 case Match_InvalidUImm5:
1531 case Match_InvalidUImm5NonZero:
1533 case Match_InvalidUImm5GT3:
1535 case Match_InvalidUImm6:
1537 case Match_InvalidUImm7:
1539 case Match_InvalidUImm8:
1541 case Match_InvalidUImm8GE32:
1543 case Match_InvalidSImm5:
1546 case Match_InvalidSImm6:
1549 case Match_InvalidSImm6NonZero:
1550 return generateImmOutOfRangeError(
1552 "immediate must be non-zero in the range");
1553 case Match_InvalidCLUIImm:
1554 return generateImmOutOfRangeError(
1556 "immediate must be in [0xfffe0, 0xfffff] or");
1557 case Match_InvalidUImm5Lsb0:
1558 return generateImmOutOfRangeError(
1560 "immediate must be a multiple of 2 bytes in the range");
1561 case Match_InvalidUImm6Lsb0:
1562 return generateImmOutOfRangeError(
1564 "immediate must be a multiple of 2 bytes in the range");
1565 case Match_InvalidUImm7Lsb00:
1566 return generateImmOutOfRangeError(
1568 "immediate must be a multiple of 4 bytes in the range");
1569 case Match_InvalidUImm8Lsb00:
1570 return generateImmOutOfRangeError(
1572 "immediate must be a multiple of 4 bytes in the range");
1573 case Match_InvalidUImm8Lsb000:
1574 return generateImmOutOfRangeError(
1576 "immediate must be a multiple of 8 bytes in the range");
1577 case Match_InvalidSImm9Lsb0:
1578 return generateImmOutOfRangeError(
1580 "immediate must be a multiple of 2 bytes in the range");
1581 case Match_InvalidUImm9Lsb000:
1582 return generateImmOutOfRangeError(
1584 "immediate must be a multiple of 8 bytes in the range");
1585 case Match_InvalidUImm10Lsb00NonZero:
1586 return generateImmOutOfRangeError(
1588 "immediate must be a multiple of 4 bytes in the range");
1589 case Match_InvalidSImm10Lsb0000NonZero:
1590 return generateImmOutOfRangeError(
1592 "immediate must be a multiple of 16 bytes and non-zero in the range");
1593 case Match_InvalidUImm11:
1595 case Match_InvalidSImm12:
1596 return generateImmOutOfRangeError(
1598 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1599 "integer in the range");
1600 case Match_InvalidSImm12Lsb0:
1601 return generateImmOutOfRangeError(
1603 "immediate must be a multiple of 2 bytes in the range");
1604 case Match_InvalidSImm12Lsb00000:
1605 return generateImmOutOfRangeError(
1607 "immediate must be a multiple of 32 bytes in the range");
1608 case Match_InvalidSImm13Lsb0:
1609 return generateImmOutOfRangeError(
1611 "immediate must be a multiple of 2 bytes in the range");
1612 case Match_InvalidUImm20LUI:
1614 "operand must be a symbol with "
1615 "%hi/%tprel_hi modifier or an integer in "
1617 case Match_InvalidUImm20:
1619 case Match_InvalidUImm20AUIPC:
1620 return generateImmOutOfRangeError(
1622 "operand must be a symbol with a "
1623 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1624 "an integer in the range");
1625 case Match_InvalidSImm21Lsb0JAL:
1626 return generateImmOutOfRangeError(
1628 "immediate must be a multiple of 2 bytes in the range");
1629 case Match_InvalidCSRSystemRegister: {
1631 "operand must be a valid system register "
1632 "name or an integer in the range");
1634 case Match_InvalidLoadFPImm: {
1636 return Error(ErrorLoc,
"operand must be a valid floating-point constant");
1638 case Match_InvalidBareSymbol: {
1640 return Error(ErrorLoc,
"operand must be a bare symbol name");
1642 case Match_InvalidPseudoJumpSymbol: {
1644 return Error(ErrorLoc,
"operand must be a valid jump target");
1646 case Match_InvalidCallSymbol: {
1648 return Error(ErrorLoc,
"operand must be a bare symbol name");
1650 case Match_InvalidTPRelAddSymbol: {
1652 return Error(ErrorLoc,
"operand must be a symbol with %tprel_add modifier");
1654 case Match_InvalidTLSDESCCallSymbol: {
1656 return Error(ErrorLoc,
1657 "operand must be a symbol with %tlsdesc_call modifier");
1659 case Match_InvalidRTZArg: {
1661 return Error(ErrorLoc,
"operand must be 'rtz' floating-point rounding mode");
1663 case Match_InvalidVTypeI: {
1665 return generateVTypeError(ErrorLoc);
1667 case Match_InvalidVMaskRegister: {
1669 return Error(ErrorLoc,
"operand must be v0.t");
1671 case Match_InvalidSImm5Plus1: {
1674 "immediate must be in the range");
1676 case Match_InvalidRlist: {
1680 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1682 case Match_InvalidStackAdj: {
1686 "stack adjustment is invalid for this instruction and register list; "
1687 "refer to Zc spec for a detailed range of stack adjustment");
1689 case Match_InvalidRnumArg: {
1692 case Match_InvalidRegReg: {
1694 return Error(ErrorLoc,
"operands must be register and register");
1712 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1713 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1716 if (isRVE() &&
Reg >= RISCV::X16 &&
Reg <= RISCV::X31)
1723 if (!tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess())
1724 return Error(StartLoc,
"invalid register name");
1730 const AsmToken &Tok = getParser().getTok();
1745 SMLoc FirstS = getLoc();
1746 bool HadParens =
false;
1753 size_t ReadCount = getLexer().peekTokens(Buf);
1756 LParen = getParser().getTok();
1761 switch (getLexer().getKind()) {
1764 getLexer().UnLex(LParen);
1772 getLexer().UnLex(LParen);
1776 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1780 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
1785 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1796 switch (getLexer().getKind()) {
1806 if (getParser().parseExpression(Res,
E))
1809 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1811 int64_t
Imm =
CE->getValue();
1812 if (isUInt<7>(Imm)) {
1813 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1822 if (getParser().parseIdentifier(Identifier))
1825 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1827 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1828 "Unexpected opcode");
1831 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1841 return generateImmOutOfRangeError(
1843 "opcode must be a valid opcode name or an immediate in the range");
1851 switch (getLexer().getKind()) {
1861 if (getParser().parseExpression(Res,
E))
1864 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1866 int64_t
Imm =
CE->getValue();
1867 if (Imm >= 0 && Imm <= 2) {
1868 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1877 if (getParser().parseIdentifier(Identifier))
1881 if (Identifier ==
"C0")
1883 else if (Identifier ==
"C1")
1885 else if (Identifier ==
"C2")
1892 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1901 return generateImmOutOfRangeError(
1903 "opcode must be a valid opcode name or an immediate in the range");
1910 auto SysRegFromConstantInt = [
this](
const MCExpr *
E,
SMLoc S) {
1911 if (
auto *CE = dyn_cast<MCConstantExpr>(
E)) {
1912 int64_t
Imm =
CE->getValue();
1913 if (isUInt<12>(Imm)) {
1914 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1919 return RISCVOperand::createSysReg(
Reg.Name, S, Imm);
1923 return RISCVOperand::createSysReg(
"", S, Imm);
1926 return std::unique_ptr<RISCVOperand>();
1929 switch (getLexer().getKind()) {
1939 if (getParser().parseExpression(Res))
1942 if (
auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1943 Operands.push_back(std::move(SysOpnd));
1947 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1951 if (getParser().parseIdentifier(Identifier))
1954 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1956 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1958 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1959 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
1960 SysReg->Name +
"'");
1964 const auto &FeatureBits = getSTI().getFeatureBits();
1965 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
1967 return SysReg->FeaturesRequired[Feature.Value];
1969 auto ErrorMsg = std::string(
"system register '") + SysReg->Name +
"' ";
1970 if (SysReg->isRV32Only && FeatureBits[RISCV::Feature64Bit]) {
1971 ErrorMsg +=
"is RV32 only";
1973 ErrorMsg +=
" and ";
1977 "requires '" + std::string(Feature->Key) +
"' to be enabled";
1980 return Error(S, ErrorMsg);
1983 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1988 MCSymbol *
Sym = getContext().lookupSymbol(Identifier);
1989 if (
Sym &&
Sym->isVariable()) {
1992 if (
auto SysOpnd = SysRegFromConstantInt(
1993 Sym->getVariableValue(
false), S)) {
1994 Operands.push_back(std::move(SysOpnd));
1999 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2000 "operand must be a valid system register "
2001 "name or an integer in the range");
2005 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2018 if (
Identifier.compare_insensitive(
"inf") == 0) {
2021 getTok().getEndLoc(), isRV64()));
2022 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
2025 getTok().getEndLoc(), isRV64()));
2026 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
2029 getTok().getEndLoc(), isRV64()));
2031 return TokError(
"invalid floating point literal");
2044 return TokError(
"invalid floating point immediate");
2047 APFloat RealVal(APFloat::IEEEdouble());
2049 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
2051 return TokError(
"invalid floating point representation");
2054 RealVal.changeSign();
2056 Operands.push_back(RISCVOperand::createFPImm(
2057 RealVal.bitcastToAPInt().getZExtValue(), S));
2069 switch (getLexer().getKind()) {
2081 if (getParser().parseExpression(Res,
E))
2085 return parseOperandWithModifier(
Operands);
2088 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2100 return Error(getLoc(),
"expected valid identifier for operand modifier");
2104 return Error(getLoc(),
"unrecognized operand modifier");
2111 if (getParser().parseParenExpression(SubExpr,
E))
2115 Operands.push_back(RISCVOperand::createImm(ModExpr, S,
E, isRV64()));
2127 AsmToken Tok = getLexer().getTok();
2129 if (getParser().parseIdentifier(Identifier))
2135 return Error(getLoc(),
"'@plt' operand not valid for instruction");
2137 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2139 if (
Sym->isVariable()) {
2140 const MCExpr *
V =
Sym->getVariableValue(
false);
2141 if (!isa<MCSymbolRefExpr>(V)) {
2142 getLexer().UnLex(Tok);
2150 switch (getLexer().getKind()) {
2152 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2165 if (getParser().parseExpression(Expr,
E))
2168 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2184 if (getParser().parseIdentifier(Identifier))
2192 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2195 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2204 if (getParser().parseExpression(Res,
E))
2207 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef ||
2208 cast<MCSymbolRefExpr>(Res)->getKind() ==
2209 MCSymbolRefExpr::VariantKind::VK_PLT)
2210 return Error(S,
"operand must be a valid jump target");
2213 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2234bool RISCVAsmParser::parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
2235 unsigned &Sew,
unsigned &Lmul,
2236 bool &Fractional,
bool &TailAgnostic,
2237 bool &MaskAgnostic) {
2244 case VTypeState_SEW:
2251 State = VTypeState_LMUL;
2253 case VTypeState_LMUL: {
2263 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2264 unsigned MinLMUL = ELEN / 8;
2267 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2268 Twine(MinLMUL) +
" is reserved");
2271 State = VTypeState_TailPolicy;
2274 case VTypeState_TailPolicy:
2275 if (Identifier ==
"ta")
2276 TailAgnostic =
true;
2277 else if (Identifier ==
"tu")
2278 TailAgnostic =
false;
2281 State = VTypeState_MaskPolicy;
2283 case VTypeState_MaskPolicy:
2284 if (Identifier ==
"ma")
2285 MaskAgnostic =
true;
2286 else if (Identifier ==
"mu")
2287 MaskAgnostic =
false;
2290 State = VTypeState_Done;
2292 case VTypeState_Done:
2305 bool Fractional =
false;
2306 bool TailAgnostic =
false;
2307 bool MaskAgnostic =
false;
2309 VTypeState State = VTypeState_SEW;
2312 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2319 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2329 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2330 unsigned MaxSEW = ELEN / Lmul;
2332 if (MaxSEW >= 8 && Sew > MaxSEW)
2334 "use of vtype encodings with SEW > " +
Twine(MaxSEW) +
2335 " and LMUL == mf" +
Twine(Lmul) +
2336 " may not be compatible with all RVV implementations");
2341 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2345 return generateVTypeError(S);
2348bool RISCVAsmParser::generateVTypeError(
SMLoc ErrorLoc) {
2352 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2360 if (!
Name.consume_back(
".t"))
2361 return Error(getLoc(),
"expected '.t' suffix");
2366 if (
Reg != RISCV::V0)
2371 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
2376 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2394 Operands.push_back(RISCVOperand::createReg(
2395 Reg, S,
E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2400 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2412 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2415 if ((
Reg - RISCV::X0) & 1) {
2418 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2419 return TokError(
"double precision floating point operands must use even "
2420 "numbered X register");
2430 Reg, RISCV::sub_gpr_even,
2431 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2432 Operands.push_back(RISCVOperand::createReg(Pair, S,
E,
true));
2436template <
bool IsRV64>
2438 return parseGPRPair(
Operands, IsRV64);
2448 if (!IsRV64Inst && isRV64())
2460 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2463 if ((
Reg - RISCV::X0) & 1)
2464 return TokError(
"register must be even");
2472 Reg, RISCV::sub_gpr_even,
2473 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2474 Operands.push_back(RISCVOperand::createReg(Pair, S,
E));
2481 "operand must be a valid floating point rounding mode mnemonic");
2483 StringRef Str = getLexer().getTok().getIdentifier();
2488 "operand must be a valid floating point rounding mode mnemonic");
2490 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2496 const AsmToken &Tok = getLexer().getTok();
2502 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2516 for (
char c : Str) {
2545 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2551 return TokError(
"operand must be formed of letters selected in-order from "
2558 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2560 if (!parseRegister(
Operands).isSuccess())
2561 return Error(getLoc(),
"expected register");
2565 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2589 std::unique_ptr<RISCVOperand> OptionalImmOp;
2596 SMLoc ImmStart = getLoc();
2597 if (getParser().parseIntToken(ImmVal,
2598 "expected '(' or optional integer offset"))
2603 SMLoc ImmEnd = getLoc();
2606 ImmStart, ImmEnd, isRV64());
2610 OptionalImmOp ?
"expected '(' after optional integer offset"
2611 :
"expected '(' or optional integer offset"))
2614 if (!parseRegister(
Operands).isSuccess())
2615 return Error(getLoc(),
"expected register");
2621 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2623 OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2624 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2637 return Error(getLoc(),
"invalid register");
2644 return Error(getLoc(),
"expected register");
2646 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2649 return Error(getLoc(),
"invalid register");
2655 Operands.push_back(RISCVOperand::createRegReg(
Reg, Reg2, getLoc()));
2668 bool IsEABI = isRVE();
2671 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2676 if (RegStart != RISCV::X1)
2677 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2683 return Error(getLoc(),
"invalid register");
2687 return Error(getLoc(),
"invalid register");
2688 if (RegStart != RISCV::X8)
2689 return Error(getLoc(),
2690 "continuous register list must start from 's0' or 'x8'");
2696 StringRef EndName = getLexer().getTok().getIdentifier();
2700 return Error(getLoc(),
"invalid register");
2701 if (IsEABI && RegEnd != RISCV::X9)
2702 return Error(getLoc(),
"contiguous register list of EABI can only be "
2703 "'s0-s1' or 'x8-x9' pair");
2710 if (RegEnd != RISCV::X9)
2713 "first contiguous registers pair of register list must be 'x8-x9'");
2717 return Error(getLoc(),
"invalid register");
2718 StringRef EndName = getLexer().getTok().getIdentifier();
2720 return Error(getLoc(),
2721 "second contiguous registers pair of register list "
2722 "must start from 'x18'");
2728 return Error(getLoc(),
"invalid register");
2729 EndName = getLexer().getTok().getIdentifier();
2731 return Error(getLoc(),
"invalid register");
2738 if (RegEnd == RISCV::X26)
2739 return Error(getLoc(),
"invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2740 "x18-x26} is not supported");
2750 return Error(S,
"invalid register list");
2751 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2757 bool ExpectNegative) {
2763 unsigned RlistVal =
static_cast<RISCVOperand *
>(
Operands[1].get())->Rlist.Val;
2765 if (Negative != ExpectNegative ||
2768 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2780 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2787 if (parseRegister(
Operands,
true).isSuccess())
2794 return !parseMemOpBaseReg(
Operands).isSuccess();
2799 Error(getLoc(),
"unknown operand");
2812 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2813 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2814 if (Assembler !=
nullptr) {
2822 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2841 if (getParser().parseEOL(
"unexpected token")) {
2842 getParser().eatToEndOfStatement();
2848bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2852 if (
const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2853 Kind = RE->getKind();
2854 Expr = RE->getSubExpr();
2864bool RISCVAsmParser::isSymbolDiff(
const MCExpr *Expr) {
2877 if (IDVal ==
".option")
2878 return parseDirectiveOption();
2879 if (IDVal ==
".attribute")
2880 return parseDirectiveAttribute();
2881 if (IDVal ==
".insn")
2882 return parseDirectiveInsn(DirectiveID.
getLoc());
2883 if (IDVal ==
".variant_cc")
2884 return parseDirectiveVariantCC();
2889bool RISCVAsmParser::resetToArch(
StringRef Arch,
SMLoc Loc, std::string &Result,
2890 bool FromOptionDirective) {
2893 clearFeatureBits(Feature.Value, Feature.Key);
2902 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
2903 << ErrMsg.getMessage();
2906 return Error(Loc, OutputErrMsg.str());
2911 if (ISAInfo->hasExtension(Feature.Key))
2912 setFeatureBits(Feature.Value, Feature.Key);
2914 if (FromOptionDirective) {
2915 if (ISAInfo->getXLen() == 32 && isRV64())
2916 return Error(Loc,
"bad arch string switching from rv64 to rv32");
2917 else if (ISAInfo->getXLen() == 64 && !isRV64())
2918 return Error(Loc,
"bad arch string switching from rv32 to rv64");
2921 if (ISAInfo->getXLen() == 32)
2922 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
2923 else if (ISAInfo->getXLen() == 64)
2924 setFeatureBits(RISCV::Feature64Bit,
"64bit");
2926 return Error(Loc,
"bad arch string " + Arch);
2928 Result = ISAInfo->toString();
2932bool RISCVAsmParser::parseDirectiveOption() {
2943 if (Option ==
"push") {
2947 getTargetStreamer().emitDirectiveOptionPush();
2952 if (Option ==
"pop") {
2957 getTargetStreamer().emitDirectiveOptionPop();
2958 if (popFeatureBits())
2959 return Error(StartLoc,
".option pop with no .option push");
2964 if (Option ==
"arch") {
2972 Type = RISCVOptionArchArgType::Plus;
2974 Type = RISCVOptionArchArgType::Minus;
2975 else if (!
Args.empty())
2977 "unexpected token, expected + or -");
2979 Type = RISCVOptionArchArgType::Full;
2983 "unexpected token, expected identifier");
2989 if (
Type == RISCVOptionArchArgType::Full) {
2991 if (resetToArch(Arch, Loc, Result,
true))
3000 Loc,
"extension version number parsing not currently implemented");
3003 if (!enableExperimentalExtension() &&
3005 return Error(Loc,
"unexpected experimental extensions");
3008 return Error(Loc,
"unknown extension feature");
3012 if (
Type == RISCVOptionArchArgType::Plus) {
3015 setFeatureBits(
Ext->Value,
Ext->Key);
3018 copySTI().setFeatureBits(OldFeatureBits);
3019 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3024 OutputErrMsg << ErrMsg.getMessage();
3027 return Error(Loc, OutputErrMsg.str());
3030 assert(
Type == RISCVOptionArchArgType::Minus);
3035 if (getSTI().hasFeature(Feature.Value) &&
3036 Feature.Implies.test(
Ext->Value))
3038 " extension; " + Feature.Key +
3039 " extension requires " +
Ext->Key +
3043 clearFeatureBits(
Ext->Value,
Ext->Key);
3050 getTargetStreamer().emitDirectiveOptionArch(Args);
3054 if (Option ==
"rvc") {
3058 getTargetStreamer().emitDirectiveOptionRVC();
3059 setFeatureBits(RISCV::FeatureStdExtC,
"c");
3063 if (Option ==
"norvc") {
3067 getTargetStreamer().emitDirectiveOptionNoRVC();
3068 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
3069 clearFeatureBits(RISCV::FeatureStdExtZca,
"zca");
3073 if (Option ==
"pic") {
3077 getTargetStreamer().emitDirectiveOptionPIC();
3078 ParserOptions.IsPicEnabled =
true;
3082 if (Option ==
"nopic") {
3086 getTargetStreamer().emitDirectiveOptionNoPIC();
3087 ParserOptions.IsPicEnabled =
false;
3091 if (Option ==
"relax") {
3095 getTargetStreamer().emitDirectiveOptionRelax();
3096 setFeatureBits(RISCV::FeatureRelax,
"relax");
3100 if (Option ==
"norelax") {
3104 getTargetStreamer().emitDirectiveOptionNoRelax();
3105 clearFeatureBits(RISCV::FeatureRelax,
"relax");
3111 "'rvc', 'norvc', 'arch', 'relax' or "
3120bool RISCVAsmParser::parseDirectiveAttribute() {
3127 std::optional<unsigned>
Ret =
3130 return Error(TagLoc,
"attribute name not recognised: " +
Name);
3141 if (check(!CE, TagLoc,
"expected numeric constant"))
3144 Tag =
CE->getValue();
3151 int64_t IntegerValue = 0;
3152 bool IsIntegerValue =
true;
3157 IsIntegerValue =
false;
3160 if (IsIntegerValue) {
3167 return Error(ValueExprLoc,
"expected numeric constant");
3168 IntegerValue =
CE->getValue();
3181 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3183 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3186 if (resetToArch(StringValue, ValueExprLoc, Result,
false))
3190 getTargetStreamer().emitTextAttribute(Tag, Result);
3198 .
Cases(
"r",
"r4",
"i",
"b",
"sb",
"u",
"j",
"uj",
"s",
true)
3199 .
Cases(
"cr",
"ci",
"ciw",
"css",
"cl",
"cs",
"ca",
"cb",
"cj", AllowC)
3207bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
3210 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3211 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3218 std::optional<int64_t>
Length;
3228 return Error(ErrorLoc,
3229 "instruction lengths must be a non-zero multiple of two");
3233 return Error(ErrorLoc,
3234 "instruction lengths over 64 bits are not supported");
3240 int64_t EncodingDerivedLength = ((
Value & 0b11) == 0b11) ? 4 : 2;
3245 if ((*
Length <= 4) && (*
Length != EncodingDerivedLength))
3246 return Error(ErrorLoc,
3247 "instruction length does not match the encoding");
3250 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3253 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3256 if (!AllowC && (EncodingDerivedLength == 2))
3257 return Error(ErrorLoc,
"compressed instructions are not allowed");
3259 if (getParser().parseEOL(
"invalid operand for instruction")) {
3260 getParser().eatToEndOfStatement();
3268 Opcode = RISCV::Insn16;
3271 Opcode = RISCV::Insn32;
3274 Opcode = RISCV::Insn48;
3277 Opcode = RISCV::Insn64;
3283 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3290 return Error(ErrorLoc,
"invalid instruction format");
3292 std::string FormatName = (
".insn_" +
Format).str();
3309bool RISCVAsmParser::parseDirectiveVariantCC() {
3311 if (getParser().parseIdentifier(
Name))
3312 return TokError(
"expected symbol name");
3315 getTargetStreamer().emitDirectiveVariantCC(
3316 *getContext().getOrCreateSymbol(
Name));
3324 ++RISCVNumInstrsCompressed;
3333 for (
MCInst &Inst : Seq) {
3334 emitToStreamer(Out, Inst);
3341 unsigned SecondOpcode,
SMLoc IDLoc,
3355 const MCExpr *RefToLinkTmpLabel =
3362 .addExpr(RefToLinkTmpLabel));
3365void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
3376 RISCV::ADDI, IDLoc, Out);
3379void RISCVAsmParser::emitLoadGlobalAddress(
MCInst &Inst,
SMLoc IDLoc,
3389 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3391 SecondOpcode, IDLoc, Out);
3394void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
3403 if (ParserOptions.IsPicEnabled)
3404 emitLoadGlobalAddress(Inst, IDLoc, Out);
3406 emitLoadLocalAddress(Inst, IDLoc, Out);
3409void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
3419 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3421 SecondOpcode, IDLoc, Out);
3424void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
3435 RISCV::ADDI, IDLoc, Out);
3438void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
3448 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3450 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3454 Opcode, IDLoc, Out);
3457void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
3458 int64_t Width,
SMLoc IDLoc,
3470 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3471 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3473 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
3486void RISCVAsmParser::emitVMSGE(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
3510 "The destination register should not be V0.");
3529 "The destination register should be V0.");
3531 "The temporary vector register should not be V0.");
3550 "The temporary vector register should not be V0.");
3575bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
3577 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
3580 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3581 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
3582 "%tprel_add modifier");
3588bool RISCVAsmParser::checkPseudoTLSDESCCall(
MCInst &Inst,
3590 assert(Inst.
getOpcode() == RISCV::PseudoTLSDESCCall &&
"Invalid instruction");
3593 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3594 return Error(ErrorLoc,
"the output operand must be t0/x5 when using "
3595 "%tlsdesc_call modifier");
3601std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
3605std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
3606 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3610std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp()
const {
3611 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3615bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
3619 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3620 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3623 if (DestReg == TempReg) {
3625 return Error(Loc,
"the temporary vector register cannot be the same as "
3626 "the destination register");
3630 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3631 Opcode == RISCV::TH_LWD) {
3636 if (Rs1 == Rd1 && Rs1 == Rd2) {
3638 return Error(Loc,
"rs1, rd1, and rd2 cannot all be the same");
3642 if (Opcode == RISCV::CM_MVSA01) {
3647 return Error(Loc,
"rs1 and rs2 must be different");
3651 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3652 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3653 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3658 return Error(Loc,
"operand must be constant 3");
3661 return Error(Loc,
"operand must be constant 4");
3668 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3669 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3675 if (VCIXDst == VCIXRs1)
3676 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3677 " overlap the source vector register group");
3681 if (VCIXDst == VCIXRs2)
3682 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3683 " overlap the source vector register group");
3698 if (DestReg == CheckReg)
3699 return Error(Loc,
"the destination vector register group cannot overlap"
3700 " the source vector register group");
3704 if (DestReg == CheckReg)
3705 return Error(Loc,
"the destination vector register group cannot overlap"
3706 " the source vector register group");
3711 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3712 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3713 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3714 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3715 Opcode == RISCV::VMERGE_VXM)
3716 return Error(Loc,
"the destination vector register group cannot be V0");
3723 assert((CheckReg == RISCV::V0 || !CheckReg) &&
3724 "Unexpected register for mask operand");
3726 if (DestReg == CheckReg)
3727 return Error(Loc,
"the destination vector register group cannot overlap"
3728 " the mask register");
3733bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
3741 case RISCV::PseudoC_ADDI_NOP:
3744 case RISCV::PseudoLLAImm:
3745 case RISCV::PseudoLAImm:
3746 case RISCV::PseudoLI: {
3763 Imm = SignExtend64<32>(Imm);
3764 emitLoadImm(
Reg, Imm, Out);
3767 case RISCV::PseudoLLA:
3768 emitLoadLocalAddress(Inst, IDLoc, Out);
3770 case RISCV::PseudoLGA:
3771 emitLoadGlobalAddress(Inst, IDLoc, Out);
3773 case RISCV::PseudoLA:
3774 emitLoadAddress(Inst, IDLoc, Out);
3776 case RISCV::PseudoLA_TLS_IE:
3777 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3779 case RISCV::PseudoLA_TLS_GD:
3780 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3782 case RISCV::PseudoLB:
3783 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
3785 case RISCV::PseudoLBU:
3786 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
3788 case RISCV::PseudoLH:
3789 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
3791 case RISCV::PseudoLHU:
3792 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
3794 case RISCV::PseudoLW:
3795 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
3797 case RISCV::PseudoLWU:
3798 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
3800 case RISCV::PseudoLD:
3801 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
3803 case RISCV::PseudoFLH:
3804 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
3806 case RISCV::PseudoFLW:
3807 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
3809 case RISCV::PseudoFLD:
3810 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
3812 case RISCV::PseudoSB:
3813 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
3815 case RISCV::PseudoSH:
3816 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
3818 case RISCV::PseudoSW:
3819 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
3821 case RISCV::PseudoSD:
3822 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
3824 case RISCV::PseudoFSH:
3825 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
3827 case RISCV::PseudoFSW:
3828 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
3830 case RISCV::PseudoFSD:
3831 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
3833 case RISCV::PseudoAddTPRel:
3834 if (checkPseudoAddTPRel(Inst,
Operands))
3837 case RISCV::PseudoTLSDESCCall:
3838 if (checkPseudoTLSDESCCall(Inst,
Operands))
3841 case RISCV::PseudoSEXT_B:
3842 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
3844 case RISCV::PseudoSEXT_H:
3845 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
3847 case RISCV::PseudoZEXT_H:
3848 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
3850 case RISCV::PseudoZEXT_W:
3851 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
3853 case RISCV::PseudoVMSGEU_VX:
3854 case RISCV::PseudoVMSGEU_VX_M:
3855 case RISCV::PseudoVMSGEU_VX_M_T:
3856 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3858 case RISCV::PseudoVMSGE_VX:
3859 case RISCV::PseudoVMSGE_VX_M:
3860 case RISCV::PseudoVMSGE_VX_M_T:
3861 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3863 case RISCV::PseudoVMSGE_VI:
3864 case RISCV::PseudoVMSLT_VI: {
3868 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3878 case RISCV::PseudoVMSGEU_VI:
3879 case RISCV::PseudoVMSLTU_VI: {
3886 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3897 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3912 emitToStreamer(Out, Inst);
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
static bool matchRegisterNameHelper(const MCSubtargetInfo &STI, MCRegister &Reg, StringRef Name)
#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")
PowerPC TLS Dynamic Call Fixup
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)
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.
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
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
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 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.
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.
virtual MCContext & getContext()=0
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
const MCObjectFileInfo * getObjectFileInfo() const
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.
bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
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.
Wrapper class representing physical registers. Should be passed by value.
constexpr unsigned id() const
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)
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 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.
This represents an "assembler immediate".
uint32_t getRefKind() const
const MCSymbolRefExpr * getSymB() const
const MCSymbolRefExpr * getSymA() 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 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)
@ VK_RISCV_TLSDESC_ADD_LO
@ VK_RISCV_TLSDESC_LOAD_LO
static VariantKind getVariantKindForName(StringRef name)
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.
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)
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
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...
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...
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]
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
Used to provide key value pairs for feature and CPU bit flags.