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_InvalidVMaskCarryInRegister: {
1686 return Error(ErrorLoc,
"operand must be v0");
1688 case Match_InvalidSImm5Plus1: {
1691 "immediate must be in the range");
1693 case Match_InvalidSImm26:
1696 case Match_InvalidRlist: {
1700 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1702 case Match_InvalidStackAdj: {
1706 "stack adjustment is invalid for this instruction and register list; "
1707 "refer to Zc spec for a detailed range of stack adjustment");
1709 case Match_InvalidRnumArg: {
1712 case Match_InvalidRegReg: {
1714 return Error(ErrorLoc,
"operands must be register and register");
1732 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1733 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1736 if (isRVE() &&
Reg >= RISCV::X16 &&
Reg <= RISCV::X31)
1743 if (!tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess())
1744 return Error(StartLoc,
"invalid register name");
1750 const AsmToken &Tok = getParser().getTok();
1765 SMLoc FirstS = getLoc();
1766 bool HadParens =
false;
1773 size_t ReadCount = getLexer().peekTokens(Buf);
1776 LParen = getParser().getTok();
1781 switch (getLexer().getKind()) {
1784 getLexer().UnLex(LParen);
1792 getLexer().UnLex(LParen);
1796 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1800 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
1805 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1816 switch (getLexer().getKind()) {
1826 if (getParser().parseExpression(Res,
E))
1829 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1831 int64_t
Imm =
CE->getValue();
1832 if (isUInt<7>(Imm)) {
1833 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1842 if (getParser().parseIdentifier(Identifier))
1845 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1847 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1848 "Unexpected opcode");
1851 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1861 return generateImmOutOfRangeError(
1863 "opcode must be a valid opcode name or an immediate in the range");
1871 switch (getLexer().getKind()) {
1881 if (getParser().parseExpression(Res,
E))
1884 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1886 int64_t
Imm =
CE->getValue();
1887 if (Imm >= 0 && Imm <= 2) {
1888 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1897 if (getParser().parseIdentifier(Identifier))
1901 if (Identifier ==
"C0")
1903 else if (Identifier ==
"C1")
1905 else if (Identifier ==
"C2")
1912 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1921 return generateImmOutOfRangeError(
1923 "opcode must be a valid opcode name or an immediate in the range");
1930 auto SysRegFromConstantInt = [
this](
const MCExpr *
E,
SMLoc S) {
1931 if (
auto *CE = dyn_cast<MCConstantExpr>(
E)) {
1932 int64_t
Imm =
CE->getValue();
1933 if (isUInt<12>(Imm)) {
1934 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1938 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1941 return RISCVOperand::createSysReg(
Reg.Name, S, Imm);
1945 return RISCVOperand::createSysReg(
"", S, Imm);
1948 return std::unique_ptr<RISCVOperand>();
1951 switch (getLexer().getKind()) {
1961 if (getParser().parseExpression(Res))
1964 if (
auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1965 Operands.push_back(std::move(SysOpnd));
1969 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1973 if (getParser().parseIdentifier(Identifier))
1976 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1979 if (SysReg->IsDeprecatedName) {
1981 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);
1983 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1985 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
1991 const auto &FeatureBits = getSTI().getFeatureBits();
1992 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
1994 return SysReg->FeaturesRequired[Feature.Value];
1996 auto ErrorMsg = std::string(
"system register '") + SysReg->Name +
"' ";
1997 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
1998 ErrorMsg +=
"is RV32 only";
2000 ErrorMsg +=
" and ";
2004 "requires '" + std::string(Feature->Key) +
"' to be enabled";
2007 return Error(S, ErrorMsg);
2010 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
2015 MCSymbol *
Sym = getContext().lookupSymbol(Identifier);
2016 if (
Sym &&
Sym->isVariable()) {
2019 if (
auto SysOpnd = SysRegFromConstantInt(
2020 Sym->getVariableValue(
false), S)) {
2021 Operands.push_back(std::move(SysOpnd));
2026 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2027 "operand must be a valid system register "
2028 "name or an integer in the range");
2032 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2045 if (
Identifier.compare_insensitive(
"inf") == 0) {
2048 getTok().getEndLoc(), isRV64()));
2049 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
2052 getTok().getEndLoc(), isRV64()));
2053 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
2056 getTok().getEndLoc(), isRV64()));
2058 return TokError(
"invalid floating point literal");
2071 return TokError(
"invalid floating point immediate");
2074 APFloat RealVal(APFloat::IEEEdouble());
2076 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
2078 return TokError(
"invalid floating point representation");
2081 RealVal.changeSign();
2083 Operands.push_back(RISCVOperand::createFPImm(
2084 RealVal.bitcastToAPInt().getZExtValue(), S));
2096 switch (getLexer().getKind()) {
2108 if (getParser().parseExpression(Res,
E))
2112 return parseOperandWithModifier(
Operands);
2115 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2127 return Error(getLoc(),
"expected valid identifier for operand modifier");
2131 return Error(getLoc(),
"unrecognized operand modifier");
2138 if (getParser().parseParenExpression(SubExpr,
E))
2142 Operands.push_back(RISCVOperand::createImm(ModExpr, S,
E, isRV64()));
2154 AsmToken Tok = getLexer().getTok();
2156 if (getParser().parseIdentifier(Identifier))
2162 return Error(getLoc(),
"'@plt' operand not valid for instruction");
2164 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2166 if (
Sym->isVariable()) {
2167 const MCExpr *
V =
Sym->getVariableValue(
false);
2168 if (!isa<MCSymbolRefExpr>(V)) {
2169 getLexer().UnLex(Tok);
2177 switch (getLexer().getKind()) {
2179 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2192 if (getParser().parseExpression(Expr,
E))
2195 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2211 if (getParser().parseIdentifier(Identifier))
2219 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2222 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2231 if (getParser().parseExpression(Res,
E))
2234 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef ||
2235 cast<MCSymbolRefExpr>(Res)->getKind() ==
2236 MCSymbolRefExpr::VariantKind::VK_PLT)
2237 return Error(S,
"operand must be a valid jump target");
2240 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2261bool RISCVAsmParser::parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
2262 unsigned &Sew,
unsigned &Lmul,
2263 bool &Fractional,
bool &TailAgnostic,
2264 bool &MaskAgnostic) {
2271 case VTypeState_SEW:
2278 State = VTypeState_LMUL;
2280 case VTypeState_LMUL: {
2290 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2291 unsigned MinLMUL = ELEN / 8;
2294 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2295 Twine(MinLMUL) +
" is reserved");
2298 State = VTypeState_TailPolicy;
2301 case VTypeState_TailPolicy:
2302 if (Identifier ==
"ta")
2303 TailAgnostic =
true;
2304 else if (Identifier ==
"tu")
2305 TailAgnostic =
false;
2308 State = VTypeState_MaskPolicy;
2310 case VTypeState_MaskPolicy:
2311 if (Identifier ==
"ma")
2312 MaskAgnostic =
true;
2313 else if (Identifier ==
"mu")
2314 MaskAgnostic =
false;
2317 State = VTypeState_Done;
2319 case VTypeState_Done:
2332 bool Fractional =
false;
2333 bool TailAgnostic =
false;
2334 bool MaskAgnostic =
false;
2336 VTypeState State = VTypeState_SEW;
2339 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2346 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2356 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2357 unsigned MaxSEW = ELEN / Lmul;
2359 if (MaxSEW >= 8 && Sew > MaxSEW)
2361 "use of vtype encodings with SEW > " +
Twine(MaxSEW) +
2362 " and LMUL == mf" +
Twine(Lmul) +
2363 " may not be compatible with all RVV implementations");
2368 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2372 return generateVTypeError(S);
2375bool RISCVAsmParser::generateVTypeError(
SMLoc ErrorLoc) {
2379 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2387 if (!
Name.consume_back(
".t"))
2388 return Error(getLoc(),
"expected '.t' suffix");
2393 if (
Reg != RISCV::V0)
2398 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
2403 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2421 Operands.push_back(RISCVOperand::createReg(
2422 Reg, S,
E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2427 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2439 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2442 if ((
Reg - RISCV::X0) & 1) {
2445 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2446 return TokError(
"double precision floating point operands must use even "
2447 "numbered X register");
2457 Reg, RISCV::sub_gpr_even,
2458 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2459 Operands.push_back(RISCVOperand::createReg(Pair, S,
E,
true));
2463template <
bool IsRV64>
2465 return parseGPRPair(
Operands, IsRV64);
2475 if (!IsRV64Inst && isRV64())
2487 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2490 if ((
Reg - RISCV::X0) & 1)
2491 return TokError(
"register must be even");
2499 Reg, RISCV::sub_gpr_even,
2500 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2501 Operands.push_back(RISCVOperand::createReg(Pair, S,
E));
2508 "operand must be a valid floating point rounding mode mnemonic");
2510 StringRef Str = getLexer().getTok().getIdentifier();
2515 "operand must be a valid floating point rounding mode mnemonic");
2517 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2523 const AsmToken &Tok = getLexer().getTok();
2529 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2543 for (
char c : Str) {
2572 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2578 return TokError(
"operand must be formed of letters selected in-order from "
2585 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2587 if (!parseRegister(
Operands).isSuccess())
2588 return Error(getLoc(),
"expected register");
2592 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2616 std::unique_ptr<RISCVOperand> OptionalImmOp;
2623 SMLoc ImmStart = getLoc();
2624 if (getParser().parseIntToken(ImmVal,
2625 "expected '(' or optional integer offset"))
2630 SMLoc ImmEnd = getLoc();
2633 ImmStart, ImmEnd, isRV64());
2637 OptionalImmOp ?
"expected '(' after optional integer offset"
2638 :
"expected '(' or optional integer offset"))
2641 if (!parseRegister(
Operands).isSuccess())
2642 return Error(getLoc(),
"expected register");
2648 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2650 OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2651 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2664 return Error(getLoc(),
"invalid register");
2671 return Error(getLoc(),
"expected register");
2673 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2676 return Error(getLoc(),
"invalid register");
2682 Operands.push_back(RISCVOperand::createRegReg(
Reg, Reg2, getLoc()));
2695 bool IsEABI = isRVE();
2698 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2703 if (RegStart != RISCV::X1)
2704 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2710 return Error(getLoc(),
"invalid register");
2714 return Error(getLoc(),
"invalid register");
2715 if (RegStart != RISCV::X8)
2716 return Error(getLoc(),
2717 "continuous register list must start from 's0' or 'x8'");
2723 StringRef EndName = getLexer().getTok().getIdentifier();
2727 return Error(getLoc(),
"invalid register");
2728 if (IsEABI && RegEnd != RISCV::X9)
2729 return Error(getLoc(),
"contiguous register list of EABI can only be "
2730 "'s0-s1' or 'x8-x9' pair");
2737 if (RegEnd != RISCV::X9)
2740 "first contiguous registers pair of register list must be 'x8-x9'");
2744 return Error(getLoc(),
"invalid register");
2745 StringRef EndName = getLexer().getTok().getIdentifier();
2747 return Error(getLoc(),
2748 "second contiguous registers pair of register list "
2749 "must start from 'x18'");
2755 return Error(getLoc(),
"invalid register");
2756 EndName = getLexer().getTok().getIdentifier();
2758 return Error(getLoc(),
"invalid register");
2765 if (RegEnd == RISCV::X26)
2766 return Error(getLoc(),
"invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2767 "x18-x26} is not supported");
2777 return Error(S,
"invalid register list");
2778 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2784 bool ExpectNegative) {
2790 unsigned RlistVal =
static_cast<RISCVOperand *
>(
Operands[1].get())->Rlist.Val;
2792 if (Negative != ExpectNegative ||
2795 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2807 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2814 if (parseRegister(
Operands,
true).isSuccess())
2821 return !parseMemOpBaseReg(
Operands).isSuccess();
2826 Error(getLoc(),
"unknown operand");
2839 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2840 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2841 if (Assembler !=
nullptr) {
2849 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2868 if (getParser().parseEOL(
"unexpected token")) {
2869 getParser().eatToEndOfStatement();
2875bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2879 if (
const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2880 Kind = RE->getKind();
2881 Expr = RE->getSubExpr();
2891bool RISCVAsmParser::isSymbolDiff(
const MCExpr *Expr) {
2904 if (IDVal ==
".option")
2905 return parseDirectiveOption();
2906 if (IDVal ==
".attribute")
2907 return parseDirectiveAttribute();
2908 if (IDVal ==
".insn")
2909 return parseDirectiveInsn(DirectiveID.
getLoc());
2910 if (IDVal ==
".variant_cc")
2911 return parseDirectiveVariantCC();
2916bool RISCVAsmParser::resetToArch(
StringRef Arch,
SMLoc Loc, std::string &Result,
2917 bool FromOptionDirective) {
2920 clearFeatureBits(Feature.Value, Feature.Key);
2929 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
2930 << ErrMsg.getMessage();
2933 return Error(Loc, OutputErrMsg.str());
2938 if (ISAInfo->hasExtension(Feature.Key))
2939 setFeatureBits(Feature.Value, Feature.Key);
2941 if (FromOptionDirective) {
2942 if (ISAInfo->getXLen() == 32 && isRV64())
2943 return Error(Loc,
"bad arch string switching from rv64 to rv32");
2944 else if (ISAInfo->getXLen() == 64 && !isRV64())
2945 return Error(Loc,
"bad arch string switching from rv32 to rv64");
2948 if (ISAInfo->getXLen() == 32)
2949 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
2950 else if (ISAInfo->getXLen() == 64)
2951 setFeatureBits(RISCV::Feature64Bit,
"64bit");
2953 return Error(Loc,
"bad arch string " + Arch);
2955 Result = ISAInfo->toString();
2959bool RISCVAsmParser::parseDirectiveOption() {
2970 if (Option ==
"push") {
2974 getTargetStreamer().emitDirectiveOptionPush();
2979 if (Option ==
"pop") {
2984 getTargetStreamer().emitDirectiveOptionPop();
2985 if (popFeatureBits())
2986 return Error(StartLoc,
".option pop with no .option push");
2991 if (Option ==
"arch") {
2999 Type = RISCVOptionArchArgType::Plus;
3001 Type = RISCVOptionArchArgType::Minus;
3002 else if (!
Args.empty())
3004 "unexpected token, expected + or -");
3006 Type = RISCVOptionArchArgType::Full;
3010 "unexpected token, expected identifier");
3016 if (
Type == RISCVOptionArchArgType::Full) {
3018 if (resetToArch(Arch, Loc, Result,
true))
3027 Loc,
"extension version number parsing not currently implemented");
3030 if (!enableExperimentalExtension() &&
3032 return Error(Loc,
"unexpected experimental extensions");
3035 return Error(Loc,
"unknown extension feature");
3039 if (
Type == RISCVOptionArchArgType::Plus) {
3042 setFeatureBits(
Ext->Value,
Ext->Key);
3045 copySTI().setFeatureBits(OldFeatureBits);
3046 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3051 OutputErrMsg << ErrMsg.getMessage();
3054 return Error(Loc, OutputErrMsg.str());
3057 assert(
Type == RISCVOptionArchArgType::Minus);
3062 if (getSTI().hasFeature(Feature.Value) &&
3063 Feature.Implies.test(
Ext->Value))
3065 " extension; " + Feature.Key +
3066 " extension requires " +
Ext->Key +
3070 clearFeatureBits(
Ext->Value,
Ext->Key);
3077 getTargetStreamer().emitDirectiveOptionArch(Args);
3081 if (Option ==
"rvc") {
3085 getTargetStreamer().emitDirectiveOptionRVC();
3086 setFeatureBits(RISCV::FeatureStdExtC,
"c");
3090 if (Option ==
"norvc") {
3094 getTargetStreamer().emitDirectiveOptionNoRVC();
3095 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
3096 clearFeatureBits(RISCV::FeatureStdExtZca,
"zca");
3100 if (Option ==
"pic") {
3104 getTargetStreamer().emitDirectiveOptionPIC();
3105 ParserOptions.IsPicEnabled =
true;
3109 if (Option ==
"nopic") {
3113 getTargetStreamer().emitDirectiveOptionNoPIC();
3114 ParserOptions.IsPicEnabled =
false;
3118 if (Option ==
"relax") {
3122 getTargetStreamer().emitDirectiveOptionRelax();
3123 setFeatureBits(RISCV::FeatureRelax,
"relax");
3127 if (Option ==
"norelax") {
3131 getTargetStreamer().emitDirectiveOptionNoRelax();
3132 clearFeatureBits(RISCV::FeatureRelax,
"relax");
3138 "'rvc', 'norvc', 'arch', 'relax' or "
3147bool RISCVAsmParser::parseDirectiveAttribute() {
3154 std::optional<unsigned>
Ret =
3157 return Error(TagLoc,
"attribute name not recognised: " +
Name);
3168 if (check(!CE, TagLoc,
"expected numeric constant"))
3171 Tag =
CE->getValue();
3178 int64_t IntegerValue = 0;
3179 bool IsIntegerValue =
true;
3184 IsIntegerValue =
false;
3187 if (IsIntegerValue) {
3194 return Error(ValueExprLoc,
"expected numeric constant");
3195 IntegerValue =
CE->getValue();
3208 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3210 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3213 if (resetToArch(StringValue, ValueExprLoc, Result,
false))
3217 getTargetStreamer().emitTextAttribute(Tag, Result);
3225 .
Cases(
"r",
"r4",
"i",
"b",
"sb",
"u",
"j",
"uj",
"s",
true)
3226 .
Cases(
"cr",
"ci",
"ciw",
"css",
"cl",
"cs",
"ca",
"cb",
"cj", AllowC)
3234bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
3237 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3238 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3245 std::optional<int64_t>
Length;
3255 return Error(ErrorLoc,
3256 "instruction lengths must be a non-zero multiple of two");
3260 return Error(ErrorLoc,
3261 "instruction lengths over 64 bits are not supported");
3267 int64_t EncodingDerivedLength = ((
Value & 0b11) == 0b11) ? 4 : 2;
3272 if ((*
Length <= 4) && (*
Length != EncodingDerivedLength))
3273 return Error(ErrorLoc,
3274 "instruction length does not match the encoding");
3277 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3280 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3283 if (!AllowC && (EncodingDerivedLength == 2))
3284 return Error(ErrorLoc,
"compressed instructions are not allowed");
3286 if (getParser().parseEOL(
"invalid operand for instruction")) {
3287 getParser().eatToEndOfStatement();
3295 Opcode = RISCV::Insn16;
3298 Opcode = RISCV::Insn32;
3301 Opcode = RISCV::Insn48;
3304 Opcode = RISCV::Insn64;
3310 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3317 return Error(ErrorLoc,
"invalid instruction format");
3319 std::string FormatName = (
".insn_" +
Format).str();
3336bool RISCVAsmParser::parseDirectiveVariantCC() {
3338 if (getParser().parseIdentifier(
Name))
3339 return TokError(
"expected symbol name");
3342 getTargetStreamer().emitDirectiveVariantCC(
3343 *getContext().getOrCreateSymbol(
Name));
3351 ++RISCVNumInstrsCompressed;
3360 for (
MCInst &Inst : Seq) {
3361 emitToStreamer(Out, Inst);
3368 unsigned SecondOpcode,
SMLoc IDLoc,
3382 const MCExpr *RefToLinkTmpLabel =
3389 .addExpr(RefToLinkTmpLabel));
3392void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
3403 RISCV::ADDI, IDLoc, Out);
3406void RISCVAsmParser::emitLoadGlobalAddress(
MCInst &Inst,
SMLoc IDLoc,
3416 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3418 SecondOpcode, IDLoc, Out);
3421void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
3430 if (ParserOptions.IsPicEnabled)
3431 emitLoadGlobalAddress(Inst, IDLoc, Out);
3433 emitLoadLocalAddress(Inst, IDLoc, Out);
3436void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
3446 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3448 SecondOpcode, IDLoc, Out);
3451void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
3462 RISCV::ADDI, IDLoc, Out);
3465void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
3475 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3477 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3481 Opcode, IDLoc, Out);
3484void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
3485 int64_t Width,
SMLoc IDLoc,
3497 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3498 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3500 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
3513void RISCVAsmParser::emitVMSGE(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
3537 "The destination register should not be V0.");
3556 "The destination register should be V0.");
3558 "The temporary vector register should not be V0.");
3577 "The temporary vector register should not be V0.");
3602bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
3604 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
3607 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3608 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
3609 "%tprel_add modifier");
3615bool RISCVAsmParser::checkPseudoTLSDESCCall(
MCInst &Inst,
3617 assert(Inst.
getOpcode() == RISCV::PseudoTLSDESCCall &&
"Invalid instruction");
3620 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3621 return Error(ErrorLoc,
"the output operand must be t0/x5 when using "
3622 "%tlsdesc_call modifier");
3628std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
3632std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
3633 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3637std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp()
const {
3638 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3642bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
3646 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3647 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3650 if (DestReg == TempReg) {
3652 return Error(Loc,
"the temporary vector register cannot be the same as "
3653 "the destination register");
3657 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3658 Opcode == RISCV::TH_LWD) {
3663 if (Rs1 == Rd1 && Rs1 == Rd2) {
3665 return Error(Loc,
"rs1, rd1, and rd2 cannot all be the same");
3669 if (Opcode == RISCV::CM_MVSA01) {
3674 return Error(Loc,
"rs1 and rs2 must be different");
3678 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3679 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3680 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3685 return Error(Loc,
"operand must be constant 3");
3688 return Error(Loc,
"operand must be constant 4");
3695 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3696 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3702 if (VCIXDst == VCIXRs1)
3703 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3704 " overlap the source vector register group");
3708 if (VCIXDst == VCIXRs2)
3709 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3710 " overlap the source vector register group");
3725 if (DestReg == CheckReg)
3726 return Error(Loc,
"the destination vector register group cannot overlap"
3727 " the source vector register group");
3731 if (DestReg == CheckReg)
3732 return Error(Loc,
"the destination vector register group cannot overlap"
3733 " the source vector register group");
3738 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3739 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3740 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3741 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3742 Opcode == RISCV::VMERGE_VXM)
3743 return Error(Loc,
"the destination vector register group cannot be V0");
3750 assert((CheckReg == RISCV::V0 || !CheckReg) &&
3751 "Unexpected register for mask operand");
3753 if (DestReg == CheckReg)
3754 return Error(Loc,
"the destination vector register group cannot overlap"
3755 " the mask register");
3760bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
3768 case RISCV::PseudoC_ADDI_NOP:
3771 case RISCV::PseudoLLAImm:
3772 case RISCV::PseudoLAImm:
3773 case RISCV::PseudoLI: {
3790 Imm = SignExtend64<32>(Imm);
3791 emitLoadImm(
Reg, Imm, Out);
3794 case RISCV::PseudoLLA:
3795 emitLoadLocalAddress(Inst, IDLoc, Out);
3797 case RISCV::PseudoLGA:
3798 emitLoadGlobalAddress(Inst, IDLoc, Out);
3800 case RISCV::PseudoLA:
3801 emitLoadAddress(Inst, IDLoc, Out);
3803 case RISCV::PseudoLA_TLS_IE:
3804 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3806 case RISCV::PseudoLA_TLS_GD:
3807 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3809 case RISCV::PseudoLB:
3810 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
3812 case RISCV::PseudoLBU:
3813 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
3815 case RISCV::PseudoLH:
3816 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
3818 case RISCV::PseudoLHU:
3819 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
3821 case RISCV::PseudoLW:
3822 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
3824 case RISCV::PseudoLWU:
3825 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
3827 case RISCV::PseudoLD:
3828 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
3830 case RISCV::PseudoFLH:
3831 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
3833 case RISCV::PseudoFLW:
3834 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
3836 case RISCV::PseudoFLD:
3837 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
3839 case RISCV::PseudoSB:
3840 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
3842 case RISCV::PseudoSH:
3843 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
3845 case RISCV::PseudoSW:
3846 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
3848 case RISCV::PseudoSD:
3849 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
3851 case RISCV::PseudoFSH:
3852 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
3854 case RISCV::PseudoFSW:
3855 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
3857 case RISCV::PseudoFSD:
3858 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
3860 case RISCV::PseudoAddTPRel:
3861 if (checkPseudoAddTPRel(Inst,
Operands))
3864 case RISCV::PseudoTLSDESCCall:
3865 if (checkPseudoTLSDESCCall(Inst,
Operands))
3868 case RISCV::PseudoSEXT_B:
3869 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
3871 case RISCV::PseudoSEXT_H:
3872 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
3874 case RISCV::PseudoZEXT_H:
3875 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
3877 case RISCV::PseudoZEXT_W:
3878 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
3880 case RISCV::PseudoVMSGEU_VX:
3881 case RISCV::PseudoVMSGEU_VX_M:
3882 case RISCV::PseudoVMSGEU_VX_M_T:
3883 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3885 case RISCV::PseudoVMSGE_VX:
3886 case RISCV::PseudoVMSGE_VX_M:
3887 case RISCV::PseudoVMSGE_VX_M_T:
3888 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3890 case RISCV::PseudoVMSGE_VI:
3891 case RISCV::PseudoVMSLT_VI: {
3895 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3905 case RISCV::PseudoVMSGEU_VI:
3906 case RISCV::PseudoVMSLTU_VI: {
3913 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3924 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3939 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.