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 isUImm10()
const {
return IsUImm<10>(); }
721 bool isUImm11()
const {
return IsUImm<11>(); }
722 bool isUImm16()
const {
return IsUImm<16>(); }
723 bool isUImm20()
const {
return IsUImm<20>(); }
724 bool isUImm32()
const {
return IsUImm<32>(); }
725 bool isUImm48()
const {
return IsUImm<48>(); }
726 bool isUImm64()
const {
return IsUImm<64>(); }
728 bool isUImm5NonZero()
const {
733 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
734 return IsConstantImm && isUInt<5>(Imm) && (
Imm != 0) &&
738 bool isUImm5GT3()
const {
743 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
744 return IsConstantImm && isUInt<5>(Imm) && (
Imm > 3) &&
748 bool isUImm8GE32()
const {
753 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
754 return IsConstantImm && isUInt<8>(Imm) &&
Imm >= 32 &&
758 bool isRnumArg()
const {
763 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
764 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(10) &&
768 bool isRnumArg_0_7()
const {
773 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
774 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(7) &&
778 bool isRnumArg_1_10()
const {
783 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
784 return IsConstantImm &&
Imm >= INT64_C(1) &&
Imm <= INT64_C(10) &&
788 bool isRnumArg_2_14()
const {
793 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
794 return IsConstantImm &&
Imm >= INT64_C(2) &&
Imm <= INT64_C(14) &&
798 bool isSImm5()
const {
803 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
804 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
808 bool isSImm6()
const {
813 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
814 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
818 bool isSImm6NonZero()
const {
823 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
824 return IsConstantImm &&
Imm != 0 &&
825 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
829 bool isCLUIImm()
const {
834 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
835 return IsConstantImm && (
Imm != 0) &&
836 (isUInt<5>(Imm) || (
Imm >= 0xfffe0 &&
Imm <= 0xfffff)) &&
840 bool isUImm2Lsb0()
const {
845 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
846 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
850 bool isUImm5Lsb0()
const {
855 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
856 return IsConstantImm && isShiftedUInt<4, 1>(Imm) &&
860 bool isUImm6Lsb0()
const {
865 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
866 return IsConstantImm && isShiftedUInt<5, 1>(Imm) &&
870 bool isUImm7Lsb00()
const {
875 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
876 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
880 bool isUImm8Lsb00()
const {
885 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
886 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
890 bool isUImm8Lsb000()
const {
895 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
896 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
900 bool isSImm9Lsb0()
const {
return isBareSimmNLsb0<9>(); }
902 bool isUImm9Lsb000()
const {
907 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
908 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
912 bool isUImm10Lsb00NonZero()
const {
917 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
918 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (
Imm != 0) &&
924 static int64_t fixImmediateForRV32(int64_t Imm,
bool IsRV64Imm) {
925 if (IsRV64Imm || !isUInt<32>(Imm))
927 return SignExtend64<32>(Imm);
930 bool isSImm12()
const {
936 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
938 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
940 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
949 bool isSImm12Lsb0()
const {
return isBareSimmNLsb0<12>(); }
951 bool isSImm12Lsb00000()
const {
956 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
957 return IsConstantImm &&
958 isShiftedInt<7, 5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
962 bool isSImm13Lsb0()
const {
return isBareSimmNLsb0<13>(); }
964 bool isSImm10Lsb0000NonZero()
const {
969 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
970 return IsConstantImm && (
Imm != 0) &&
971 isShiftedInt<6, 4>(fixImmediateForRV32(Imm, isRV64Imm())) &&
975 bool isUImm20LUI()
const {
981 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
982 if (!IsConstantImm) {
983 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
993 bool isUImm20AUIPC()
const {
999 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1000 if (!IsConstantImm) {
1001 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
1017 bool isSImm21Lsb0JAL()
const {
return isBareSimmNLsb0<21>(); }
1019 bool isImmZero()
const {
1024 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1028 bool isSImm5Plus1()
const {
1033 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1034 return IsConstantImm &&
1035 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
1039 bool isSImm26()
const {
1044 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1046 isInt<26>(fixImmediateForRV32(Imm, isRV64Imm()));
1050 SMLoc getStartLoc()
const override {
return StartLoc; }
1052 SMLoc getEndLoc()
const override {
return EndLoc; }
1054 bool isRV64Imm()
const {
1055 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1060 assert(Kind == KindTy::Register &&
"Invalid type access!");
1065 assert(Kind == KindTy::SystemRegister &&
"Invalid type access!");
1066 return StringRef(SysReg.Data, SysReg.Length);
1069 const MCExpr *getImm()
const {
1070 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1075 assert(Kind == KindTy::FPImmediate &&
"Invalid type access!");
1080 assert(Kind == KindTy::Token &&
"Invalid type access!");
1084 unsigned getVType()
const {
1085 assert(Kind == KindTy::VType &&
"Invalid type access!");
1090 assert(Kind == KindTy::FRM &&
"Invalid type access!");
1094 unsigned getFence()
const {
1095 assert(Kind == KindTy::Fence &&
"Invalid type access!");
1108 case KindTy::Immediate:
1111 case KindTy::FPImmediate:
1113 case KindTy::Register:
1117 OS <<
"'" << getToken() <<
"'";
1119 case KindTy::SystemRegister:
1120 OS <<
"<sysreg: " << getSysReg() <<
'>';
1129 roundingModeToString(getFRM());
1147 case KindTy::RegReg:
1154 static std::unique_ptr<RISCVOperand> createToken(
StringRef Str,
SMLoc S) {
1155 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1162 static std::unique_ptr<RISCVOperand>
1164 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1165 Op->Reg.RegNum =
Reg.id();
1166 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1172 static std::unique_ptr<RISCVOperand> createImm(
const MCExpr *Val,
SMLoc S,
1174 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1176 Op->Imm.IsRV64 = IsRV64;
1182 static std::unique_ptr<RISCVOperand> createFPImm(
uint64_t Val,
SMLoc S) {
1183 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1184 Op->FPImm.Val = Val;
1190 static std::unique_ptr<RISCVOperand> createSysReg(
StringRef Str,
SMLoc S,
1191 unsigned Encoding) {
1192 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1193 Op->SysReg.Data = Str.data();
1194 Op->SysReg.Length = Str.size();
1201 static std::unique_ptr<RISCVOperand>
1203 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1210 static std::unique_ptr<RISCVOperand> createFenceArg(
unsigned Val,
SMLoc S) {
1211 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1212 Op->Fence.Val = Val;
1218 static std::unique_ptr<RISCVOperand> createVType(
unsigned VTypeI,
SMLoc S) {
1219 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1220 Op->VType.Val = VTypeI;
1226 static std::unique_ptr<RISCVOperand> createRlist(
unsigned RlistEncode,
1228 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1229 Op->Rlist.Val = RlistEncode;
1234 static std::unique_ptr<RISCVOperand> createRegReg(
MCRegister Reg1,
1236 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1237 Op->RegReg.Reg1 = Reg1.
id();
1238 Op->RegReg.Reg2 = Reg2.
id();
1244 static std::unique_ptr<RISCVOperand> createSpimm(
unsigned Spimm,
SMLoc S) {
1245 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1246 Op->Spimm.Val = Spimm;
1251 static void addExpr(
MCInst &Inst,
const MCExpr *Expr,
bool IsRV64Imm) {
1252 assert(Expr &&
"Expr shouldn't be null!");
1255 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1265 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
1266 assert(
N == 1 &&
"Invalid number of operands!");
1270 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
1271 assert(
N == 1 &&
"Invalid number of operands!");
1272 addExpr(Inst, getImm(), isRV64Imm());
1275 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
1276 assert(
N == 1 &&
"Invalid number of operands!");
1278 addExpr(Inst, getImm(), isRV64Imm());
1283 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
1287 void addFenceArgOperands(
MCInst &Inst,
unsigned N)
const {
1288 assert(
N == 1 &&
"Invalid number of operands!");
1292 void addCSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
1293 assert(
N == 1 &&
"Invalid number of operands!");
1300 void addVTypeIOperands(
MCInst &Inst,
unsigned N)
const {
1301 assert(
N == 1 &&
"Invalid number of operands!");
1303 if (Kind == KindTy::Immediate) {
1305 [[maybe_unused]]
bool IsConstantImm =
1306 evaluateConstantImm(getImm(), Imm, VK);
1307 assert(IsConstantImm &&
"Invalid VTypeI Operand!");
1314 void addRlistOperands(
MCInst &Inst,
unsigned N)
const {
1315 assert(
N == 1 &&
"Invalid number of operands!");
1319 void addRegRegOperands(
MCInst &Inst,
unsigned N)
const {
1320 assert(
N == 2 &&
"Invalid number of operands!");
1325 void addSpimmOperands(
MCInst &Inst,
unsigned N)
const {
1326 assert(
N == 1 &&
"Invalid number of operands!");
1330 void addFRMArgOperands(
MCInst &Inst,
unsigned N)
const {
1331 assert(
N == 1 &&
"Invalid number of operands!");
1337#define GET_REGISTER_MATCHER
1338#define GET_SUBTARGET_FEATURE_NAME
1339#define GET_MATCHER_IMPLEMENTATION
1340#define GET_MNEMONIC_SPELL_CHECKER
1341#include "RISCVGenAsmMatcher.inc"
1344 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1345 return Reg - RISCV::F0_D + RISCV::F0_H;
1349 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1350 return Reg - RISCV::F0_D + RISCV::F0_F;
1355 unsigned RegClassID;
1356 if (Kind == MCK_VRM2)
1357 RegClassID = RISCV::VRM2RegClassID;
1358 else if (Kind == MCK_VRM4)
1359 RegClassID = RISCV::VRM4RegClassID;
1360 else if (Kind == MCK_VRM8)
1361 RegClassID = RISCV::VRM8RegClassID;
1365 &RISCVMCRegisterClasses[RegClassID]);
1370 RISCVOperand &
Op =
static_cast<RISCVOperand &
>(AsmOp);
1372 return Match_InvalidOperand;
1376 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg);
1378 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
Reg);
1379 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg);
1383 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1384 (IsRegFPR64C &&
Kind == MCK_FPR32C)) {
1386 return Match_Success;
1390 if (IsRegFPR64 && Kind == MCK_FPR16) {
1392 return Match_Success;
1394 if (Kind == MCK_GPRAsFPR16 &&
Op.isGPRAsFPR()) {
1395 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_H;
1396 return Match_Success;
1398 if (Kind == MCK_GPRAsFPR32 &&
Op.isGPRAsFPR()) {
1399 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_W;
1400 return Match_Success;
1407 if (RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg) &&
1408 Kind == MCK_GPRF64AsFPR && STI->
hasFeature(RISCV::FeatureStdExtZdinx) &&
1410 return Match_Success;
1414 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1417 return Match_InvalidOperand;
1418 return Match_Success;
1420 return Match_InvalidOperand;
1423bool RISCVAsmParser::generateImmOutOfRangeError(
1425 const Twine &Msg =
"immediate must be an integer in the range") {
1429bool RISCVAsmParser::generateImmOutOfRangeError(
1431 const Twine &Msg =
"immediate must be an integer in the range") {
1433 return generateImmOutOfRangeError(ErrorLoc,
Lower,
Upper, Msg);
1436bool RISCVAsmParser::matchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1440 bool MatchingInlineAsm) {
1450 if (validateInstruction(Inst,
Operands))
1452 return processInstruction(Inst, IDLoc,
Operands, Out);
1453 case Match_MissingFeature: {
1454 assert(MissingFeatures.
any() &&
"Unknown missing features!");
1455 bool FirstFeature =
true;
1456 std::string Msg =
"instruction requires the following:";
1457 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
1458 if (MissingFeatures[i]) {
1459 Msg += FirstFeature ?
" " :
", ";
1461 FirstFeature =
false;
1464 return Error(IDLoc, Msg);
1466 case Match_MnemonicFail: {
1467 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1468 std::string Suggestion = RISCVMnemonicSpellCheck(
1469 ((RISCVOperand &)*
Operands[0]).getToken(), FBS, 0);
1470 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
1472 case Match_InvalidOperand: {
1473 SMLoc ErrorLoc = IDLoc;
1476 return Error(ErrorLoc,
"too few operands for instruction");
1479 if (ErrorLoc ==
SMLoc())
1482 return Error(ErrorLoc,
"invalid operand for instruction");
1489 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1490 SMLoc ErrorLoc = IDLoc;
1492 return Error(ErrorLoc,
"too few operands for instruction");
1498 case Match_InvalidImmXLenLI:
1501 return Error(ErrorLoc,
"operand must be a constant 64-bit integer");
1504 std::numeric_limits<int32_t>::min(),
1505 std::numeric_limits<uint32_t>::max());
1506 case Match_InvalidImmXLenLI_Restricted:
1509 return Error(ErrorLoc,
"operand either must be a constant 64-bit integer "
1510 "or a bare symbol name");
1512 return generateImmOutOfRangeError(
1514 std::numeric_limits<uint32_t>::max(),
1515 "operand either must be a bare symbol name or an immediate integer in "
1517 case Match_InvalidImmZero: {
1519 return Error(ErrorLoc,
"immediate must be zero");
1521 case Match_InvalidUImmLog2XLen:
1525 case Match_InvalidUImmLog2XLenNonZero:
1529 case Match_InvalidUImm1:
1531 case Match_InvalidUImm2:
1533 case Match_InvalidUImm2Lsb0:
1535 "immediate must be one of");
1536 case Match_InvalidUImm3:
1538 case Match_InvalidUImm4:
1540 case Match_InvalidUImm5:
1542 case Match_InvalidUImm5NonZero:
1544 case Match_InvalidUImm5GT3:
1546 case Match_InvalidUImm6:
1548 case Match_InvalidUImm7:
1550 case Match_InvalidUImm8:
1552 case Match_InvalidUImm8GE32:
1554 case Match_InvalidSImm5:
1557 case Match_InvalidSImm6:
1560 case Match_InvalidSImm6NonZero:
1561 return generateImmOutOfRangeError(
1563 "immediate must be non-zero in the range");
1564 case Match_InvalidCLUIImm:
1565 return generateImmOutOfRangeError(
1567 "immediate must be in [0xfffe0, 0xfffff] or");
1568 case Match_InvalidUImm5Lsb0:
1569 return generateImmOutOfRangeError(
1571 "immediate must be a multiple of 2 bytes in the range");
1572 case Match_InvalidUImm6Lsb0:
1573 return generateImmOutOfRangeError(
1575 "immediate must be a multiple of 2 bytes in the range");
1576 case Match_InvalidUImm7Lsb00:
1577 return generateImmOutOfRangeError(
1579 "immediate must be a multiple of 4 bytes in the range");
1580 case Match_InvalidUImm8Lsb00:
1581 return generateImmOutOfRangeError(
1583 "immediate must be a multiple of 4 bytes in the range");
1584 case Match_InvalidUImm8Lsb000:
1585 return generateImmOutOfRangeError(
1587 "immediate must be a multiple of 8 bytes in the range");
1588 case Match_InvalidSImm9Lsb0:
1589 return generateImmOutOfRangeError(
1591 "immediate must be a multiple of 2 bytes in the range");
1592 case Match_InvalidUImm9Lsb000:
1593 return generateImmOutOfRangeError(
1595 "immediate must be a multiple of 8 bytes in the range");
1596 case Match_InvalidUImm10Lsb00NonZero:
1597 return generateImmOutOfRangeError(
1599 "immediate must be a multiple of 4 bytes in the range");
1600 case Match_InvalidSImm10Lsb0000NonZero:
1601 return generateImmOutOfRangeError(
1603 "immediate must be a multiple of 16 bytes and non-zero in the range");
1604 case Match_InvalidUImm10:
1606 case Match_InvalidUImm11:
1608 case Match_InvalidSImm12:
1609 return generateImmOutOfRangeError(
1611 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1612 "integer in the range");
1613 case Match_InvalidSImm12Lsb0:
1614 return generateImmOutOfRangeError(
1616 "immediate must be a multiple of 2 bytes in the range");
1617 case Match_InvalidSImm12Lsb00000:
1618 return generateImmOutOfRangeError(
1620 "immediate must be a multiple of 32 bytes in the range");
1621 case Match_InvalidSImm13Lsb0:
1622 return generateImmOutOfRangeError(
1624 "immediate must be a multiple of 2 bytes in the range");
1625 case Match_InvalidUImm20LUI:
1627 "operand must be a symbol with "
1628 "%hi/%tprel_hi modifier or an integer in "
1630 case Match_InvalidUImm20:
1632 case Match_InvalidUImm20AUIPC:
1633 return generateImmOutOfRangeError(
1635 "operand must be a symbol with a "
1636 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1637 "an integer in the range");
1638 case Match_InvalidSImm21Lsb0JAL:
1639 return generateImmOutOfRangeError(
1641 "immediate must be a multiple of 2 bytes in the range");
1642 case Match_InvalidCSRSystemRegister: {
1644 "operand must be a valid system register "
1645 "name or an integer in the range");
1647 case Match_InvalidLoadFPImm: {
1649 return Error(ErrorLoc,
"operand must be a valid floating-point constant");
1651 case Match_InvalidBareSymbol: {
1653 return Error(ErrorLoc,
"operand must be a bare symbol name");
1655 case Match_InvalidPseudoJumpSymbol: {
1657 return Error(ErrorLoc,
"operand must be a valid jump target");
1659 case Match_InvalidCallSymbol: {
1661 return Error(ErrorLoc,
"operand must be a bare symbol name");
1663 case Match_InvalidTPRelAddSymbol: {
1665 return Error(ErrorLoc,
"operand must be a symbol with %tprel_add modifier");
1667 case Match_InvalidTLSDESCCallSymbol: {
1669 return Error(ErrorLoc,
1670 "operand must be a symbol with %tlsdesc_call modifier");
1672 case Match_InvalidRTZArg: {
1674 return Error(ErrorLoc,
"operand must be 'rtz' floating-point rounding mode");
1676 case Match_InvalidVTypeI: {
1678 return generateVTypeError(ErrorLoc);
1680 case Match_InvalidVMaskRegister: {
1682 return Error(ErrorLoc,
"operand must be v0.t");
1684 case Match_InvalidSImm5Plus1: {
1687 "immediate must be in the range");
1689 case Match_InvalidSImm26:
1692 case Match_InvalidRlist: {
1696 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1698 case Match_InvalidStackAdj: {
1702 "stack adjustment is invalid for this instruction and register list; "
1703 "refer to Zc spec for a detailed range of stack adjustment");
1705 case Match_InvalidRnumArg: {
1708 case Match_InvalidRegReg: {
1710 return Error(ErrorLoc,
"operands must be register and register");
1728 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1729 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1732 if (isRVE() &&
Reg >= RISCV::X16 &&
Reg <= RISCV::X31)
1739 if (!tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess())
1740 return Error(StartLoc,
"invalid register name");
1746 const AsmToken &Tok = getParser().getTok();
1761 SMLoc FirstS = getLoc();
1762 bool HadParens =
false;
1769 size_t ReadCount = getLexer().peekTokens(Buf);
1772 LParen = getParser().getTok();
1777 switch (getLexer().getKind()) {
1780 getLexer().UnLex(LParen);
1788 getLexer().UnLex(LParen);
1792 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1796 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
1801 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1812 switch (getLexer().getKind()) {
1822 if (getParser().parseExpression(Res,
E))
1825 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1827 int64_t
Imm =
CE->getValue();
1828 if (isUInt<7>(Imm)) {
1829 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1838 if (getParser().parseIdentifier(Identifier))
1841 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1843 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1844 "Unexpected opcode");
1847 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1857 return generateImmOutOfRangeError(
1859 "opcode must be a valid opcode name or an immediate in the range");
1867 switch (getLexer().getKind()) {
1877 if (getParser().parseExpression(Res,
E))
1880 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1882 int64_t
Imm =
CE->getValue();
1883 if (Imm >= 0 && Imm <= 2) {
1884 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1893 if (getParser().parseIdentifier(Identifier))
1897 if (Identifier ==
"C0")
1899 else if (Identifier ==
"C1")
1901 else if (Identifier ==
"C2")
1908 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1917 return generateImmOutOfRangeError(
1919 "opcode must be a valid opcode name or an immediate in the range");
1926 auto SysRegFromConstantInt = [
this](
const MCExpr *
E,
SMLoc S) {
1927 if (
auto *CE = dyn_cast<MCConstantExpr>(
E)) {
1928 int64_t
Imm =
CE->getValue();
1929 if (isUInt<12>(Imm)) {
1930 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1934 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1937 return RISCVOperand::createSysReg(
Reg.Name, S, Imm);
1941 return RISCVOperand::createSysReg(
"", S, Imm);
1944 return std::unique_ptr<RISCVOperand>();
1947 switch (getLexer().getKind()) {
1957 if (getParser().parseExpression(Res))
1960 if (
auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1961 Operands.push_back(std::move(SysOpnd));
1965 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1969 if (getParser().parseIdentifier(Identifier))
1972 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1975 if (SysReg->IsDeprecatedName) {
1977 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);
1979 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1981 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
1987 const auto &FeatureBits = getSTI().getFeatureBits();
1988 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
1990 return SysReg->FeaturesRequired[Feature.Value];
1992 auto ErrorMsg = std::string(
"system register '") + SysReg->Name +
"' ";
1993 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
1994 ErrorMsg +=
"is RV32 only";
1996 ErrorMsg +=
" and ";
2000 "requires '" + std::string(Feature->Key) +
"' to be enabled";
2003 return Error(S, ErrorMsg);
2006 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
2011 MCSymbol *
Sym = getContext().lookupSymbol(Identifier);
2012 if (
Sym &&
Sym->isVariable()) {
2015 if (
auto SysOpnd = SysRegFromConstantInt(
2016 Sym->getVariableValue(
false), S)) {
2017 Operands.push_back(std::move(SysOpnd));
2022 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2023 "operand must be a valid system register "
2024 "name or an integer in the range");
2028 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2041 if (
Identifier.compare_insensitive(
"inf") == 0) {
2044 getTok().getEndLoc(), isRV64()));
2045 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
2048 getTok().getEndLoc(), isRV64()));
2049 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
2052 getTok().getEndLoc(), isRV64()));
2054 return TokError(
"invalid floating point literal");
2067 return TokError(
"invalid floating point immediate");
2070 APFloat RealVal(APFloat::IEEEdouble());
2072 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
2074 return TokError(
"invalid floating point representation");
2077 RealVal.changeSign();
2079 Operands.push_back(RISCVOperand::createFPImm(
2080 RealVal.bitcastToAPInt().getZExtValue(), S));
2092 switch (getLexer().getKind()) {
2104 if (getParser().parseExpression(Res,
E))
2108 return parseOperandWithModifier(
Operands);
2111 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2123 return Error(getLoc(),
"expected valid identifier for operand modifier");
2127 return Error(getLoc(),
"unrecognized operand modifier");
2134 if (getParser().parseParenExpression(SubExpr,
E))
2138 Operands.push_back(RISCVOperand::createImm(ModExpr, S,
E, isRV64()));
2150 AsmToken Tok = getLexer().getTok();
2152 if (getParser().parseIdentifier(Identifier))
2158 return Error(getLoc(),
"'@plt' operand not valid for instruction");
2160 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2162 if (
Sym->isVariable()) {
2163 const MCExpr *
V =
Sym->getVariableValue(
false);
2164 if (!isa<MCSymbolRefExpr>(V)) {
2165 getLexer().UnLex(Tok);
2173 switch (getLexer().getKind()) {
2175 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2188 if (getParser().parseExpression(Expr,
E))
2191 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2207 if (getParser().parseIdentifier(Identifier))
2215 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2218 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2227 if (getParser().parseExpression(Res,
E))
2230 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef ||
2231 cast<MCSymbolRefExpr>(Res)->getKind() ==
2232 MCSymbolRefExpr::VariantKind::VK_PLT)
2233 return Error(S,
"operand must be a valid jump target");
2236 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2257bool RISCVAsmParser::parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
2258 unsigned &Sew,
unsigned &Lmul,
2259 bool &Fractional,
bool &TailAgnostic,
2260 bool &MaskAgnostic) {
2267 case VTypeState_SEW:
2274 State = VTypeState_LMUL;
2276 case VTypeState_LMUL: {
2286 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2287 unsigned MinLMUL = ELEN / 8;
2290 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2291 Twine(MinLMUL) +
" is reserved");
2294 State = VTypeState_TailPolicy;
2297 case VTypeState_TailPolicy:
2298 if (Identifier ==
"ta")
2299 TailAgnostic =
true;
2300 else if (Identifier ==
"tu")
2301 TailAgnostic =
false;
2304 State = VTypeState_MaskPolicy;
2306 case VTypeState_MaskPolicy:
2307 if (Identifier ==
"ma")
2308 MaskAgnostic =
true;
2309 else if (Identifier ==
"mu")
2310 MaskAgnostic =
false;
2313 State = VTypeState_Done;
2315 case VTypeState_Done:
2328 bool Fractional =
false;
2329 bool TailAgnostic =
false;
2330 bool MaskAgnostic =
false;
2332 VTypeState State = VTypeState_SEW;
2335 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2342 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2352 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2353 unsigned MaxSEW = ELEN / Lmul;
2355 if (MaxSEW >= 8 && Sew > MaxSEW)
2357 "use of vtype encodings with SEW > " +
Twine(MaxSEW) +
2358 " and LMUL == mf" +
Twine(Lmul) +
2359 " may not be compatible with all RVV implementations");
2364 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2368 return generateVTypeError(S);
2371bool RISCVAsmParser::generateVTypeError(
SMLoc ErrorLoc) {
2375 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2383 if (!
Name.consume_back(
".t"))
2384 return Error(getLoc(),
"expected '.t' suffix");
2389 if (
Reg != RISCV::V0)
2394 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
2399 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2417 Operands.push_back(RISCVOperand::createReg(
2418 Reg, S,
E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2423 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2435 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2438 if ((
Reg - RISCV::X0) & 1) {
2441 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2442 return TokError(
"double precision floating point operands must use even "
2443 "numbered X register");
2453 Reg, RISCV::sub_gpr_even,
2454 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2455 Operands.push_back(RISCVOperand::createReg(Pair, S,
E,
true));
2459template <
bool IsRV64>
2461 return parseGPRPair(
Operands, IsRV64);
2471 if (!IsRV64Inst && isRV64())
2483 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2486 if ((
Reg - RISCV::X0) & 1)
2487 return TokError(
"register must be even");
2495 Reg, RISCV::sub_gpr_even,
2496 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2497 Operands.push_back(RISCVOperand::createReg(Pair, S,
E));
2504 "operand must be a valid floating point rounding mode mnemonic");
2506 StringRef Str = getLexer().getTok().getIdentifier();
2511 "operand must be a valid floating point rounding mode mnemonic");
2513 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2519 const AsmToken &Tok = getLexer().getTok();
2525 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2539 for (
char c : Str) {
2568 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2574 return TokError(
"operand must be formed of letters selected in-order from "
2581 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2583 if (!parseRegister(
Operands).isSuccess())
2584 return Error(getLoc(),
"expected register");
2588 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2612 std::unique_ptr<RISCVOperand> OptionalImmOp;
2619 SMLoc ImmStart = getLoc();
2620 if (getParser().parseIntToken(ImmVal,
2621 "expected '(' or optional integer offset"))
2626 SMLoc ImmEnd = getLoc();
2629 ImmStart, ImmEnd, isRV64());
2633 OptionalImmOp ?
"expected '(' after optional integer offset"
2634 :
"expected '(' or optional integer offset"))
2637 if (!parseRegister(
Operands).isSuccess())
2638 return Error(getLoc(),
"expected register");
2644 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2646 OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2647 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2660 return Error(getLoc(),
"invalid register");
2667 return Error(getLoc(),
"expected register");
2669 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2672 return Error(getLoc(),
"invalid register");
2678 Operands.push_back(RISCVOperand::createRegReg(
Reg, Reg2, getLoc()));
2691 bool IsEABI = isRVE();
2694 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2699 if (RegStart != RISCV::X1)
2700 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2706 return Error(getLoc(),
"invalid register");
2710 return Error(getLoc(),
"invalid register");
2711 if (RegStart != RISCV::X8)
2712 return Error(getLoc(),
2713 "continuous register list must start from 's0' or 'x8'");
2719 StringRef EndName = getLexer().getTok().getIdentifier();
2723 return Error(getLoc(),
"invalid register");
2724 if (IsEABI && RegEnd != RISCV::X9)
2725 return Error(getLoc(),
"contiguous register list of EABI can only be "
2726 "'s0-s1' or 'x8-x9' pair");
2733 if (RegEnd != RISCV::X9)
2736 "first contiguous registers pair of register list must be 'x8-x9'");
2740 return Error(getLoc(),
"invalid register");
2741 StringRef EndName = getLexer().getTok().getIdentifier();
2743 return Error(getLoc(),
2744 "second contiguous registers pair of register list "
2745 "must start from 'x18'");
2751 return Error(getLoc(),
"invalid register");
2752 EndName = getLexer().getTok().getIdentifier();
2754 return Error(getLoc(),
"invalid register");
2761 if (RegEnd == RISCV::X26)
2762 return Error(getLoc(),
"invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2763 "x18-x26} is not supported");
2773 return Error(S,
"invalid register list");
2774 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2780 bool ExpectNegative) {
2786 unsigned RlistVal =
static_cast<RISCVOperand *
>(
Operands[1].get())->Rlist.Val;
2788 if (Negative != ExpectNegative ||
2791 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2803 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2810 if (parseRegister(
Operands,
true).isSuccess())
2817 return !parseMemOpBaseReg(
Operands).isSuccess();
2822 Error(getLoc(),
"unknown operand");
2835 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2836 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2837 if (Assembler !=
nullptr) {
2845 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2864 if (getParser().parseEOL(
"unexpected token")) {
2865 getParser().eatToEndOfStatement();
2871bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2875 if (
const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2876 Kind = RE->getKind();
2877 Expr = RE->getSubExpr();
2887bool RISCVAsmParser::isSymbolDiff(
const MCExpr *Expr) {
2900 if (IDVal ==
".option")
2901 return parseDirectiveOption();
2902 if (IDVal ==
".attribute")
2903 return parseDirectiveAttribute();
2904 if (IDVal ==
".insn")
2905 return parseDirectiveInsn(DirectiveID.
getLoc());
2906 if (IDVal ==
".variant_cc")
2907 return parseDirectiveVariantCC();
2912bool RISCVAsmParser::resetToArch(
StringRef Arch,
SMLoc Loc, std::string &Result,
2913 bool FromOptionDirective) {
2916 clearFeatureBits(Feature.Value, Feature.Key);
2925 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
2926 << ErrMsg.getMessage();
2929 return Error(Loc, OutputErrMsg.str());
2934 if (ISAInfo->hasExtension(Feature.Key))
2935 setFeatureBits(Feature.Value, Feature.Key);
2937 if (FromOptionDirective) {
2938 if (ISAInfo->getXLen() == 32 && isRV64())
2939 return Error(Loc,
"bad arch string switching from rv64 to rv32");
2940 else if (ISAInfo->getXLen() == 64 && !isRV64())
2941 return Error(Loc,
"bad arch string switching from rv32 to rv64");
2944 if (ISAInfo->getXLen() == 32)
2945 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
2946 else if (ISAInfo->getXLen() == 64)
2947 setFeatureBits(RISCV::Feature64Bit,
"64bit");
2949 return Error(Loc,
"bad arch string " + Arch);
2951 Result = ISAInfo->toString();
2955bool RISCVAsmParser::parseDirectiveOption() {
2966 if (Option ==
"push") {
2970 getTargetStreamer().emitDirectiveOptionPush();
2975 if (Option ==
"pop") {
2980 getTargetStreamer().emitDirectiveOptionPop();
2981 if (popFeatureBits())
2982 return Error(StartLoc,
".option pop with no .option push");
2987 if (Option ==
"arch") {
2995 Type = RISCVOptionArchArgType::Plus;
2997 Type = RISCVOptionArchArgType::Minus;
2998 else if (!
Args.empty())
3000 "unexpected token, expected + or -");
3002 Type = RISCVOptionArchArgType::Full;
3006 "unexpected token, expected identifier");
3012 if (
Type == RISCVOptionArchArgType::Full) {
3014 if (resetToArch(Arch, Loc, Result,
true))
3023 Loc,
"extension version number parsing not currently implemented");
3026 if (!enableExperimentalExtension() &&
3028 return Error(Loc,
"unexpected experimental extensions");
3031 return Error(Loc,
"unknown extension feature");
3035 if (
Type == RISCVOptionArchArgType::Plus) {
3038 setFeatureBits(
Ext->Value,
Ext->Key);
3041 copySTI().setFeatureBits(OldFeatureBits);
3042 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3047 OutputErrMsg << ErrMsg.getMessage();
3050 return Error(Loc, OutputErrMsg.str());
3053 assert(
Type == RISCVOptionArchArgType::Minus);
3058 if (getSTI().hasFeature(Feature.Value) &&
3059 Feature.Implies.test(
Ext->Value))
3061 " extension; " + Feature.Key +
3062 " extension requires " +
Ext->Key +
3066 clearFeatureBits(
Ext->Value,
Ext->Key);
3073 getTargetStreamer().emitDirectiveOptionArch(Args);
3077 if (Option ==
"rvc") {
3081 getTargetStreamer().emitDirectiveOptionRVC();
3082 setFeatureBits(RISCV::FeatureStdExtC,
"c");
3086 if (Option ==
"norvc") {
3090 getTargetStreamer().emitDirectiveOptionNoRVC();
3091 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
3092 clearFeatureBits(RISCV::FeatureStdExtZca,
"zca");
3096 if (Option ==
"pic") {
3100 getTargetStreamer().emitDirectiveOptionPIC();
3101 ParserOptions.IsPicEnabled =
true;
3105 if (Option ==
"nopic") {
3109 getTargetStreamer().emitDirectiveOptionNoPIC();
3110 ParserOptions.IsPicEnabled =
false;
3114 if (Option ==
"relax") {
3118 getTargetStreamer().emitDirectiveOptionRelax();
3119 setFeatureBits(RISCV::FeatureRelax,
"relax");
3123 if (Option ==
"norelax") {
3127 getTargetStreamer().emitDirectiveOptionNoRelax();
3128 clearFeatureBits(RISCV::FeatureRelax,
"relax");
3134 "'rvc', 'norvc', 'arch', 'relax' or "
3143bool RISCVAsmParser::parseDirectiveAttribute() {
3150 std::optional<unsigned>
Ret =
3153 return Error(TagLoc,
"attribute name not recognised: " +
Name);
3164 if (check(!CE, TagLoc,
"expected numeric constant"))
3167 Tag =
CE->getValue();
3174 int64_t IntegerValue = 0;
3175 bool IsIntegerValue =
true;
3180 IsIntegerValue =
false;
3183 if (IsIntegerValue) {
3190 return Error(ValueExprLoc,
"expected numeric constant");
3191 IntegerValue =
CE->getValue();
3204 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3206 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3209 if (resetToArch(StringValue, ValueExprLoc, Result,
false))
3213 getTargetStreamer().emitTextAttribute(Tag, Result);
3221 .
Cases(
"r",
"r4",
"i",
"b",
"sb",
"u",
"j",
"uj",
"s",
true)
3222 .
Cases(
"cr",
"ci",
"ciw",
"css",
"cl",
"cs",
"ca",
"cb",
"cj", AllowC)
3230bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
3233 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3234 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3241 std::optional<int64_t>
Length;
3251 return Error(ErrorLoc,
3252 "instruction lengths must be a non-zero multiple of two");
3256 return Error(ErrorLoc,
3257 "instruction lengths over 64 bits are not supported");
3263 int64_t EncodingDerivedLength = ((
Value & 0b11) == 0b11) ? 4 : 2;
3268 if ((*
Length <= 4) && (*
Length != EncodingDerivedLength))
3269 return Error(ErrorLoc,
3270 "instruction length does not match the encoding");
3273 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3276 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3279 if (!AllowC && (EncodingDerivedLength == 2))
3280 return Error(ErrorLoc,
"compressed instructions are not allowed");
3282 if (getParser().parseEOL(
"invalid operand for instruction")) {
3283 getParser().eatToEndOfStatement();
3291 Opcode = RISCV::Insn16;
3294 Opcode = RISCV::Insn32;
3297 Opcode = RISCV::Insn48;
3300 Opcode = RISCV::Insn64;
3306 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3313 return Error(ErrorLoc,
"invalid instruction format");
3315 std::string FormatName = (
".insn_" +
Format).str();
3332bool RISCVAsmParser::parseDirectiveVariantCC() {
3334 if (getParser().parseIdentifier(
Name))
3335 return TokError(
"expected symbol name");
3338 getTargetStreamer().emitDirectiveVariantCC(
3339 *getContext().getOrCreateSymbol(
Name));
3347 ++RISCVNumInstrsCompressed;
3356 for (
MCInst &Inst : Seq) {
3357 emitToStreamer(Out, Inst);
3364 unsigned SecondOpcode,
SMLoc IDLoc,
3378 const MCExpr *RefToLinkTmpLabel =
3385 .addExpr(RefToLinkTmpLabel));
3388void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
3399 RISCV::ADDI, IDLoc, Out);
3402void RISCVAsmParser::emitLoadGlobalAddress(
MCInst &Inst,
SMLoc IDLoc,
3412 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3414 SecondOpcode, IDLoc, Out);
3417void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
3426 if (ParserOptions.IsPicEnabled)
3427 emitLoadGlobalAddress(Inst, IDLoc, Out);
3429 emitLoadLocalAddress(Inst, IDLoc, Out);
3432void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
3442 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3444 SecondOpcode, IDLoc, Out);
3447void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
3458 RISCV::ADDI, IDLoc, Out);
3461void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
3471 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3473 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3477 Opcode, IDLoc, Out);
3480void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
3481 int64_t Width,
SMLoc IDLoc,
3493 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3494 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3496 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
3509void RISCVAsmParser::emitVMSGE(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
3533 "The destination register should not be V0.");
3552 "The destination register should be V0.");
3554 "The temporary vector register should not be V0.");
3573 "The temporary vector register should not be V0.");
3598bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
3600 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
3603 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3604 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
3605 "%tprel_add modifier");
3611bool RISCVAsmParser::checkPseudoTLSDESCCall(
MCInst &Inst,
3613 assert(Inst.
getOpcode() == RISCV::PseudoTLSDESCCall &&
"Invalid instruction");
3616 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3617 return Error(ErrorLoc,
"the output operand must be t0/x5 when using "
3618 "%tlsdesc_call modifier");
3624std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
3628std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
3629 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3633std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp()
const {
3634 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3638bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
3642 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3643 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3646 if (DestReg == TempReg) {
3648 return Error(Loc,
"the temporary vector register cannot be the same as "
3649 "the destination register");
3653 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3654 Opcode == RISCV::TH_LWD) {
3659 if (Rs1 == Rd1 && Rs1 == Rd2) {
3661 return Error(Loc,
"rs1, rd1, and rd2 cannot all be the same");
3665 if (Opcode == RISCV::CM_MVSA01) {
3670 return Error(Loc,
"rs1 and rs2 must be different");
3674 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3675 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3676 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3681 return Error(Loc,
"operand must be constant 3");
3684 return Error(Loc,
"operand must be constant 4");
3691 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3692 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3698 if (VCIXDst == VCIXRs1)
3699 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3700 " overlap the source vector register group");
3704 if (VCIXDst == VCIXRs2)
3705 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3706 " overlap the source vector register group");
3721 if (DestReg == CheckReg)
3722 return Error(Loc,
"the destination vector register group cannot overlap"
3723 " the source vector register group");
3727 if (DestReg == CheckReg)
3728 return Error(Loc,
"the destination vector register group cannot overlap"
3729 " the source vector register group");
3734 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3735 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3736 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3737 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3738 Opcode == RISCV::VMERGE_VXM)
3739 return Error(Loc,
"the destination vector register group cannot be V0");
3746 assert((CheckReg == RISCV::V0 || !CheckReg) &&
3747 "Unexpected register for mask operand");
3749 if (DestReg == CheckReg)
3750 return Error(Loc,
"the destination vector register group cannot overlap"
3751 " the mask register");
3756bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
3764 case RISCV::PseudoC_ADDI_NOP:
3767 case RISCV::PseudoLLAImm:
3768 case RISCV::PseudoLAImm:
3769 case RISCV::PseudoLI: {
3786 Imm = SignExtend64<32>(Imm);
3787 emitLoadImm(
Reg, Imm, Out);
3790 case RISCV::PseudoLLA:
3791 emitLoadLocalAddress(Inst, IDLoc, Out);
3793 case RISCV::PseudoLGA:
3794 emitLoadGlobalAddress(Inst, IDLoc, Out);
3796 case RISCV::PseudoLA:
3797 emitLoadAddress(Inst, IDLoc, Out);
3799 case RISCV::PseudoLA_TLS_IE:
3800 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3802 case RISCV::PseudoLA_TLS_GD:
3803 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3805 case RISCV::PseudoLB:
3806 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
3808 case RISCV::PseudoLBU:
3809 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
3811 case RISCV::PseudoLH:
3812 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
3814 case RISCV::PseudoLHU:
3815 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
3817 case RISCV::PseudoLW:
3818 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
3820 case RISCV::PseudoLWU:
3821 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
3823 case RISCV::PseudoLD:
3824 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
3826 case RISCV::PseudoFLH:
3827 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
3829 case RISCV::PseudoFLW:
3830 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
3832 case RISCV::PseudoFLD:
3833 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
3835 case RISCV::PseudoSB:
3836 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
3838 case RISCV::PseudoSH:
3839 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
3841 case RISCV::PseudoSW:
3842 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
3844 case RISCV::PseudoSD:
3845 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
3847 case RISCV::PseudoFSH:
3848 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
3850 case RISCV::PseudoFSW:
3851 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
3853 case RISCV::PseudoFSD:
3854 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
3856 case RISCV::PseudoAddTPRel:
3857 if (checkPseudoAddTPRel(Inst,
Operands))
3860 case RISCV::PseudoTLSDESCCall:
3861 if (checkPseudoTLSDESCCall(Inst,
Operands))
3864 case RISCV::PseudoSEXT_B:
3865 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
3867 case RISCV::PseudoSEXT_H:
3868 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
3870 case RISCV::PseudoZEXT_H:
3871 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
3873 case RISCV::PseudoZEXT_W:
3874 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
3876 case RISCV::PseudoVMSGEU_VX:
3877 case RISCV::PseudoVMSGEU_VX_M:
3878 case RISCV::PseudoVMSGEU_VX_M_T:
3879 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3881 case RISCV::PseudoVMSGE_VX:
3882 case RISCV::PseudoVMSGE_VX_M:
3883 case RISCV::PseudoVMSGE_VX_M_T:
3884 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3886 case RISCV::PseudoVMSGE_VI:
3887 case RISCV::PseudoVMSLT_VI: {
3891 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3901 case RISCV::PseudoVMSGEU_VI:
3902 case RISCV::PseudoVMSLTU_VI: {
3909 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3920 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3935 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.