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 isUImm7Lsb000()
const {
885 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
886 return IsConstantImm && isShiftedUInt<4, 3>(Imm) &&
890 bool isUImm8Lsb00()
const {
895 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
896 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
900 bool isUImm8Lsb000()
const {
905 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
906 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
910 bool isSImm9Lsb0()
const {
return isBareSimmNLsb0<9>(); }
912 bool isUImm9Lsb000()
const {
917 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
918 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
922 bool isUImm10Lsb00NonZero()
const {
927 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
928 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (
Imm != 0) &&
934 static int64_t fixImmediateForRV32(int64_t Imm,
bool IsRV64Imm) {
935 if (IsRV64Imm || !isUInt<32>(Imm))
937 return SignExtend64<32>(Imm);
940 bool isSImm12()
const {
946 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
948 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
950 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
959 bool isSImm12Lsb0()
const {
return isBareSimmNLsb0<12>(); }
961 bool isSImm12Lsb00000()
const {
966 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
967 return IsConstantImm &&
968 isShiftedInt<7, 5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
972 bool isSImm13Lsb0()
const {
return isBareSimmNLsb0<13>(); }
974 bool isSImm10Lsb0000NonZero()
const {
979 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
980 return IsConstantImm && (
Imm != 0) &&
981 isShiftedInt<6, 4>(fixImmediateForRV32(Imm, isRV64Imm())) &&
985 bool isUImm20LUI()
const {
991 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
992 if (!IsConstantImm) {
993 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
1003 bool isUImm20AUIPC()
const {
1009 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1010 if (!IsConstantImm) {
1011 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
1027 bool isSImm21Lsb0JAL()
const {
return isBareSimmNLsb0<21>(); }
1029 bool isImmZero()
const {
1034 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1038 bool isSImm5Plus1()
const {
1043 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1044 return IsConstantImm &&
1045 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
1049 bool isSImm26()
const {
1054 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1056 isInt<26>(fixImmediateForRV32(Imm, isRV64Imm()));
1060 SMLoc getStartLoc()
const override {
return StartLoc; }
1062 SMLoc getEndLoc()
const override {
return EndLoc; }
1064 bool isRV64Imm()
const {
1065 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1070 assert(Kind == KindTy::Register &&
"Invalid type access!");
1075 assert(Kind == KindTy::SystemRegister &&
"Invalid type access!");
1076 return StringRef(SysReg.Data, SysReg.Length);
1079 const MCExpr *getImm()
const {
1080 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1085 assert(Kind == KindTy::FPImmediate &&
"Invalid type access!");
1090 assert(Kind == KindTy::Token &&
"Invalid type access!");
1094 unsigned getVType()
const {
1095 assert(Kind == KindTy::VType &&
"Invalid type access!");
1100 assert(Kind == KindTy::FRM &&
"Invalid type access!");
1104 unsigned getFence()
const {
1105 assert(Kind == KindTy::Fence &&
"Invalid type access!");
1118 case KindTy::Immediate:
1121 case KindTy::FPImmediate:
1123 case KindTy::Register:
1127 OS <<
"'" << getToken() <<
"'";
1129 case KindTy::SystemRegister:
1130 OS <<
"<sysreg: " << getSysReg() <<
'>';
1139 roundingModeToString(getFRM());
1157 case KindTy::RegReg:
1164 static std::unique_ptr<RISCVOperand> createToken(
StringRef Str,
SMLoc S) {
1165 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1172 static std::unique_ptr<RISCVOperand>
1174 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1175 Op->Reg.RegNum =
Reg.id();
1176 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1182 static std::unique_ptr<RISCVOperand> createImm(
const MCExpr *Val,
SMLoc S,
1184 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1186 Op->Imm.IsRV64 = IsRV64;
1192 static std::unique_ptr<RISCVOperand> createFPImm(
uint64_t Val,
SMLoc S) {
1193 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1194 Op->FPImm.Val = Val;
1200 static std::unique_ptr<RISCVOperand> createSysReg(
StringRef Str,
SMLoc S,
1201 unsigned Encoding) {
1202 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1203 Op->SysReg.Data = Str.data();
1204 Op->SysReg.Length = Str.size();
1211 static std::unique_ptr<RISCVOperand>
1213 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1220 static std::unique_ptr<RISCVOperand> createFenceArg(
unsigned Val,
SMLoc S) {
1221 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1222 Op->Fence.Val = Val;
1228 static std::unique_ptr<RISCVOperand> createVType(
unsigned VTypeI,
SMLoc S) {
1229 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1230 Op->VType.Val = VTypeI;
1236 static std::unique_ptr<RISCVOperand> createRlist(
unsigned RlistEncode,
1238 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1239 Op->Rlist.Val = RlistEncode;
1244 static std::unique_ptr<RISCVOperand> createRegReg(
MCRegister Reg1,
1246 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1247 Op->RegReg.Reg1 = Reg1.
id();
1248 Op->RegReg.Reg2 = Reg2.
id();
1254 static std::unique_ptr<RISCVOperand> createSpimm(
unsigned Spimm,
SMLoc S) {
1255 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1256 Op->Spimm.Val = Spimm;
1261 static void addExpr(
MCInst &Inst,
const MCExpr *Expr,
bool IsRV64Imm) {
1262 assert(Expr &&
"Expr shouldn't be null!");
1265 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1275 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
1276 assert(
N == 1 &&
"Invalid number of operands!");
1280 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
1281 assert(
N == 1 &&
"Invalid number of operands!");
1282 addExpr(Inst, getImm(), isRV64Imm());
1285 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
1286 assert(
N == 1 &&
"Invalid number of operands!");
1288 addExpr(Inst, getImm(), isRV64Imm());
1293 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
1297 void addFenceArgOperands(
MCInst &Inst,
unsigned N)
const {
1298 assert(
N == 1 &&
"Invalid number of operands!");
1302 void addCSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
1303 assert(
N == 1 &&
"Invalid number of operands!");
1310 void addVTypeIOperands(
MCInst &Inst,
unsigned N)
const {
1311 assert(
N == 1 &&
"Invalid number of operands!");
1313 if (Kind == KindTy::Immediate) {
1315 [[maybe_unused]]
bool IsConstantImm =
1316 evaluateConstantImm(getImm(), Imm, VK);
1317 assert(IsConstantImm &&
"Invalid VTypeI Operand!");
1324 void addRlistOperands(
MCInst &Inst,
unsigned N)
const {
1325 assert(
N == 1 &&
"Invalid number of operands!");
1329 void addRegRegOperands(
MCInst &Inst,
unsigned N)
const {
1330 assert(
N == 2 &&
"Invalid number of operands!");
1335 void addSpimmOperands(
MCInst &Inst,
unsigned N)
const {
1336 assert(
N == 1 &&
"Invalid number of operands!");
1340 void addFRMArgOperands(
MCInst &Inst,
unsigned N)
const {
1341 assert(
N == 1 &&
"Invalid number of operands!");
1347#define GET_REGISTER_MATCHER
1348#define GET_SUBTARGET_FEATURE_NAME
1349#define GET_MATCHER_IMPLEMENTATION
1350#define GET_MNEMONIC_SPELL_CHECKER
1351#include "RISCVGenAsmMatcher.inc"
1354 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1355 return Reg - RISCV::F0_D + RISCV::F0_H;
1359 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1360 return Reg - RISCV::F0_D + RISCV::F0_F;
1365 unsigned RegClassID;
1366 if (Kind == MCK_VRM2)
1367 RegClassID = RISCV::VRM2RegClassID;
1368 else if (Kind == MCK_VRM4)
1369 RegClassID = RISCV::VRM4RegClassID;
1370 else if (Kind == MCK_VRM8)
1371 RegClassID = RISCV::VRM8RegClassID;
1375 &RISCVMCRegisterClasses[RegClassID]);
1380 RISCVOperand &
Op =
static_cast<RISCVOperand &
>(AsmOp);
1382 return Match_InvalidOperand;
1386 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg);
1388 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
Reg);
1389 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg);
1393 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1394 (IsRegFPR64C &&
Kind == MCK_FPR32C)) {
1396 return Match_Success;
1400 if (IsRegFPR64 && Kind == MCK_FPR16) {
1402 return Match_Success;
1404 if (Kind == MCK_GPRAsFPR16 &&
Op.isGPRAsFPR()) {
1405 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_H;
1406 return Match_Success;
1408 if (Kind == MCK_GPRAsFPR32 &&
Op.isGPRAsFPR()) {
1409 Op.Reg.RegNum =
Reg - RISCV::X0 + RISCV::X0_W;
1410 return Match_Success;
1417 if (RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg) &&
1418 Kind == MCK_GPRF64AsFPR && STI->
hasFeature(RISCV::FeatureStdExtZdinx) &&
1420 return Match_Success;
1424 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1427 return Match_InvalidOperand;
1428 return Match_Success;
1430 return Match_InvalidOperand;
1433bool RISCVAsmParser::generateImmOutOfRangeError(
1435 const Twine &Msg =
"immediate must be an integer in the range") {
1439bool RISCVAsmParser::generateImmOutOfRangeError(
1441 const Twine &Msg =
"immediate must be an integer in the range") {
1443 return generateImmOutOfRangeError(ErrorLoc,
Lower,
Upper, Msg);
1446bool RISCVAsmParser::matchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1450 bool MatchingInlineAsm) {
1460 if (validateInstruction(Inst,
Operands))
1462 return processInstruction(Inst, IDLoc,
Operands, Out);
1463 case Match_MissingFeature: {
1464 assert(MissingFeatures.
any() &&
"Unknown missing features!");
1465 bool FirstFeature =
true;
1466 std::string Msg =
"instruction requires the following:";
1467 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
1468 if (MissingFeatures[i]) {
1469 Msg += FirstFeature ?
" " :
", ";
1471 FirstFeature =
false;
1474 return Error(IDLoc, Msg);
1476 case Match_MnemonicFail: {
1477 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1478 std::string Suggestion = RISCVMnemonicSpellCheck(
1479 ((RISCVOperand &)*
Operands[0]).getToken(), FBS, 0);
1480 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
1482 case Match_InvalidOperand: {
1483 SMLoc ErrorLoc = IDLoc;
1486 return Error(ErrorLoc,
"too few operands for instruction");
1489 if (ErrorLoc ==
SMLoc())
1492 return Error(ErrorLoc,
"invalid operand for instruction");
1499 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1500 SMLoc ErrorLoc = IDLoc;
1502 return Error(ErrorLoc,
"too few operands for instruction");
1508 case Match_InvalidImmXLenLI:
1511 return Error(ErrorLoc,
"operand must be a constant 64-bit integer");
1514 std::numeric_limits<int32_t>::min(),
1515 std::numeric_limits<uint32_t>::max());
1516 case Match_InvalidImmXLenLI_Restricted:
1519 return Error(ErrorLoc,
"operand either must be a constant 64-bit integer "
1520 "or a bare symbol name");
1522 return generateImmOutOfRangeError(
1524 std::numeric_limits<uint32_t>::max(),
1525 "operand either must be a bare symbol name or an immediate integer in "
1527 case Match_InvalidImmZero: {
1529 return Error(ErrorLoc,
"immediate must be zero");
1531 case Match_InvalidUImmLog2XLen:
1535 case Match_InvalidUImmLog2XLenNonZero:
1539 case Match_InvalidUImm1:
1541 case Match_InvalidUImm2:
1543 case Match_InvalidUImm2Lsb0:
1545 "immediate must be one of");
1546 case Match_InvalidUImm3:
1548 case Match_InvalidUImm4:
1550 case Match_InvalidUImm5:
1552 case Match_InvalidUImm5NonZero:
1554 case Match_InvalidUImm5GT3:
1556 case Match_InvalidUImm6:
1558 case Match_InvalidUImm7:
1560 case Match_InvalidUImm8:
1562 case Match_InvalidUImm8GE32:
1564 case Match_InvalidSImm5:
1567 case Match_InvalidSImm6:
1570 case Match_InvalidSImm6NonZero:
1571 return generateImmOutOfRangeError(
1573 "immediate must be non-zero in the range");
1574 case Match_InvalidCLUIImm:
1575 return generateImmOutOfRangeError(
1577 "immediate must be in [0xfffe0, 0xfffff] or");
1578 case Match_InvalidUImm5Lsb0:
1579 return generateImmOutOfRangeError(
1581 "immediate must be a multiple of 2 bytes in the range");
1582 case Match_InvalidUImm6Lsb0:
1583 return generateImmOutOfRangeError(
1585 "immediate must be a multiple of 2 bytes in the range");
1586 case Match_InvalidUImm7Lsb00:
1587 return generateImmOutOfRangeError(
1589 "immediate must be a multiple of 4 bytes in the range");
1590 case Match_InvalidUImm8Lsb00:
1591 return generateImmOutOfRangeError(
1593 "immediate must be a multiple of 4 bytes in the range");
1594 case Match_InvalidUImm8Lsb000:
1595 return generateImmOutOfRangeError(
1597 "immediate must be a multiple of 8 bytes in the range");
1598 case Match_InvalidSImm9Lsb0:
1599 return generateImmOutOfRangeError(
1601 "immediate must be a multiple of 2 bytes in the range");
1602 case Match_InvalidUImm9Lsb000:
1603 return generateImmOutOfRangeError(
1605 "immediate must be a multiple of 8 bytes in the range");
1606 case Match_InvalidUImm10Lsb00NonZero:
1607 return generateImmOutOfRangeError(
1609 "immediate must be a multiple of 4 bytes in the range");
1610 case Match_InvalidSImm10Lsb0000NonZero:
1611 return generateImmOutOfRangeError(
1613 "immediate must be a multiple of 16 bytes and non-zero in the range");
1614 case Match_InvalidUImm10:
1616 case Match_InvalidUImm11:
1618 case Match_InvalidSImm12:
1619 return generateImmOutOfRangeError(
1621 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1622 "integer in the range");
1623 case Match_InvalidSImm12Lsb0:
1624 return generateImmOutOfRangeError(
1626 "immediate must be a multiple of 2 bytes in the range");
1627 case Match_InvalidSImm12Lsb00000:
1628 return generateImmOutOfRangeError(
1630 "immediate must be a multiple of 32 bytes in the range");
1631 case Match_InvalidSImm13Lsb0:
1632 return generateImmOutOfRangeError(
1634 "immediate must be a multiple of 2 bytes in the range");
1635 case Match_InvalidUImm20LUI:
1637 "operand must be a symbol with "
1638 "%hi/%tprel_hi modifier or an integer in "
1640 case Match_InvalidUImm20:
1642 case Match_InvalidUImm20AUIPC:
1643 return generateImmOutOfRangeError(
1645 "operand must be a symbol with a "
1646 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1647 "an integer in the range");
1648 case Match_InvalidSImm21Lsb0JAL:
1649 return generateImmOutOfRangeError(
1651 "immediate must be a multiple of 2 bytes in the range");
1652 case Match_InvalidCSRSystemRegister: {
1654 "operand must be a valid system register "
1655 "name or an integer in the range");
1657 case Match_InvalidLoadFPImm: {
1659 return Error(ErrorLoc,
"operand must be a valid floating-point constant");
1661 case Match_InvalidBareSymbol: {
1663 return Error(ErrorLoc,
"operand must be a bare symbol name");
1665 case Match_InvalidPseudoJumpSymbol: {
1667 return Error(ErrorLoc,
"operand must be a valid jump target");
1669 case Match_InvalidCallSymbol: {
1671 return Error(ErrorLoc,
"operand must be a bare symbol name");
1673 case Match_InvalidTPRelAddSymbol: {
1675 return Error(ErrorLoc,
"operand must be a symbol with %tprel_add modifier");
1677 case Match_InvalidTLSDESCCallSymbol: {
1679 return Error(ErrorLoc,
1680 "operand must be a symbol with %tlsdesc_call modifier");
1682 case Match_InvalidRTZArg: {
1684 return Error(ErrorLoc,
"operand must be 'rtz' floating-point rounding mode");
1686 case Match_InvalidVTypeI: {
1688 return generateVTypeError(ErrorLoc);
1690 case Match_InvalidVMaskRegister: {
1692 return Error(ErrorLoc,
"operand must be v0.t");
1694 case Match_InvalidVMaskCarryInRegister: {
1696 return Error(ErrorLoc,
"operand must be v0");
1698 case Match_InvalidSImm5Plus1: {
1701 "immediate must be in the range");
1703 case Match_InvalidSImm26:
1706 case Match_InvalidRlist: {
1710 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1712 case Match_InvalidStackAdj: {
1716 "stack adjustment is invalid for this instruction and register list; "
1717 "refer to Zc spec for a detailed range of stack adjustment");
1719 case Match_InvalidRnumArg: {
1722 case Match_InvalidRegReg: {
1724 return Error(ErrorLoc,
"operands must be register and register");
1742 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1743 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1746 if (isRVE() &&
Reg >= RISCV::X16 &&
Reg <= RISCV::X31)
1753 if (!tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess())
1754 return Error(StartLoc,
"invalid register name");
1760 const AsmToken &Tok = getParser().getTok();
1775 SMLoc FirstS = getLoc();
1776 bool HadParens =
false;
1783 size_t ReadCount = getLexer().peekTokens(Buf);
1786 LParen = getParser().getTok();
1791 switch (getLexer().getKind()) {
1794 getLexer().UnLex(LParen);
1802 getLexer().UnLex(LParen);
1806 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1810 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
1815 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1826 switch (getLexer().getKind()) {
1836 if (getParser().parseExpression(Res,
E))
1839 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1841 int64_t
Imm =
CE->getValue();
1842 if (isUInt<7>(Imm)) {
1843 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1852 if (getParser().parseIdentifier(Identifier))
1855 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1857 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1858 "Unexpected opcode");
1861 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1871 return generateImmOutOfRangeError(
1873 "opcode must be a valid opcode name or an immediate in the range");
1881 switch (getLexer().getKind()) {
1891 if (getParser().parseExpression(Res,
E))
1894 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1896 int64_t
Imm =
CE->getValue();
1897 if (Imm >= 0 && Imm <= 2) {
1898 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1907 if (getParser().parseIdentifier(Identifier))
1911 if (Identifier ==
"C0")
1913 else if (Identifier ==
"C1")
1915 else if (Identifier ==
"C2")
1922 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1931 return generateImmOutOfRangeError(
1933 "opcode must be a valid opcode name or an immediate in the range");
1940 auto SysRegFromConstantInt = [
this](
const MCExpr *
E,
SMLoc S) {
1941 if (
auto *CE = dyn_cast<MCConstantExpr>(
E)) {
1942 int64_t
Imm =
CE->getValue();
1943 if (isUInt<12>(Imm)) {
1944 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1948 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1951 return RISCVOperand::createSysReg(
Reg.Name, S, Imm);
1955 return RISCVOperand::createSysReg(
"", S, Imm);
1958 return std::unique_ptr<RISCVOperand>();
1961 switch (getLexer().getKind()) {
1971 if (getParser().parseExpression(Res))
1974 if (
auto SysOpnd = SysRegFromConstantInt(Res, S)) {
1975 Operands.push_back(std::move(SysOpnd));
1979 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1983 if (getParser().parseIdentifier(Identifier))
1986 const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1989 if (SysReg->IsDeprecatedName) {
1991 auto Range = RISCVSysReg::lookupSysRegByEncoding(SysReg->Encoding);
1993 if (
Reg.IsAltName ||
Reg.IsDeprecatedName)
1995 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
2001 const auto &FeatureBits = getSTI().getFeatureBits();
2002 if (!SysReg->haveRequiredFeatures(FeatureBits)) {
2004 return SysReg->FeaturesRequired[Feature.Value];
2006 auto ErrorMsg = std::string(
"system register '") + SysReg->Name +
"' ";
2007 if (SysReg->IsRV32Only && FeatureBits[RISCV::Feature64Bit]) {
2008 ErrorMsg +=
"is RV32 only";
2010 ErrorMsg +=
" and ";
2014 "requires '" + std::string(Feature->Key) +
"' to be enabled";
2017 return Error(S, ErrorMsg);
2020 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
2025 MCSymbol *
Sym = getContext().lookupSymbol(Identifier);
2026 if (
Sym &&
Sym->isVariable()) {
2029 if (
auto SysOpnd = SysRegFromConstantInt(
2030 Sym->getVariableValue(
false), S)) {
2031 Operands.push_back(std::move(SysOpnd));
2036 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
2037 "operand must be a valid system register "
2038 "name or an integer in the range");
2042 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
2055 if (
Identifier.compare_insensitive(
"inf") == 0) {
2058 getTok().getEndLoc(), isRV64()));
2059 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
2062 getTok().getEndLoc(), isRV64()));
2063 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
2066 getTok().getEndLoc(), isRV64()));
2068 return TokError(
"invalid floating point literal");
2081 return TokError(
"invalid floating point immediate");
2084 APFloat RealVal(APFloat::IEEEdouble());
2086 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
2088 return TokError(
"invalid floating point representation");
2091 RealVal.changeSign();
2093 Operands.push_back(RISCVOperand::createFPImm(
2094 RealVal.bitcastToAPInt().getZExtValue(), S));
2106 switch (getLexer().getKind()) {
2118 if (getParser().parseExpression(Res,
E))
2122 return parseOperandWithModifier(
Operands);
2125 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2137 return Error(getLoc(),
"expected valid identifier for operand modifier");
2141 return Error(getLoc(),
"unrecognized operand modifier");
2148 if (getParser().parseParenExpression(SubExpr,
E))
2152 Operands.push_back(RISCVOperand::createImm(ModExpr, S,
E, isRV64()));
2164 AsmToken Tok = getLexer().getTok();
2166 if (getParser().parseIdentifier(Identifier))
2172 return Error(getLoc(),
"'@plt' operand not valid for instruction");
2174 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2176 if (
Sym->isVariable()) {
2177 const MCExpr *
V =
Sym->getVariableValue(
false);
2178 if (!isa<MCSymbolRefExpr>(V)) {
2179 getLexer().UnLex(Tok);
2187 switch (getLexer().getKind()) {
2189 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2202 if (getParser().parseExpression(Expr,
E))
2205 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2221 if (getParser().parseIdentifier(Identifier))
2229 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2232 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2241 if (getParser().parseExpression(Res,
E))
2244 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef ||
2245 cast<MCSymbolRefExpr>(Res)->getKind() ==
2246 MCSymbolRefExpr::VariantKind::VK_PLT)
2247 return Error(S,
"operand must be a valid jump target");
2250 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2271bool RISCVAsmParser::parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
2272 unsigned &Sew,
unsigned &Lmul,
2273 bool &Fractional,
bool &TailAgnostic,
2274 bool &MaskAgnostic) {
2281 case VTypeState_SEW:
2288 State = VTypeState_LMUL;
2290 case VTypeState_LMUL: {
2300 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2301 unsigned MinLMUL = ELEN / 8;
2304 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2305 Twine(MinLMUL) +
" is reserved");
2308 State = VTypeState_TailPolicy;
2311 case VTypeState_TailPolicy:
2312 if (Identifier ==
"ta")
2313 TailAgnostic =
true;
2314 else if (Identifier ==
"tu")
2315 TailAgnostic =
false;
2318 State = VTypeState_MaskPolicy;
2320 case VTypeState_MaskPolicy:
2321 if (Identifier ==
"ma")
2322 MaskAgnostic =
true;
2323 else if (Identifier ==
"mu")
2324 MaskAgnostic =
false;
2327 State = VTypeState_Done;
2329 case VTypeState_Done:
2342 bool Fractional =
false;
2343 bool TailAgnostic =
false;
2344 bool MaskAgnostic =
false;
2346 VTypeState State = VTypeState_SEW;
2349 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2356 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2366 unsigned ELEN = STI->
hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2367 unsigned MaxSEW = ELEN / Lmul;
2369 if (MaxSEW >= 8 && Sew > MaxSEW)
2371 "use of vtype encodings with SEW > " +
Twine(MaxSEW) +
2372 " and LMUL == mf" +
Twine(Lmul) +
2373 " may not be compatible with all RVV implementations");
2378 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2382 return generateVTypeError(S);
2385bool RISCVAsmParser::generateVTypeError(
SMLoc ErrorLoc) {
2389 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2397 if (!
Name.consume_back(
".t"))
2398 return Error(getLoc(),
"expected '.t' suffix");
2403 if (
Reg != RISCV::V0)
2408 Operands.push_back(RISCVOperand::createReg(
Reg, S,
E));
2413 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2431 Operands.push_back(RISCVOperand::createReg(
2432 Reg, S,
E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2437 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF))
2449 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2452 if ((
Reg - RISCV::X0) & 1) {
2455 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx))
2456 return TokError(
"double precision floating point operands must use even "
2457 "numbered X register");
2467 Reg, RISCV::sub_gpr_even,
2468 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2469 Operands.push_back(RISCVOperand::createReg(Pair, S,
E,
true));
2473template <
bool IsRV64>
2475 return parseGPRPair(
Operands, IsRV64);
2485 if (!IsRV64Inst && isRV64())
2497 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(
Reg))
2500 if ((
Reg - RISCV::X0) & 1)
2501 return TokError(
"register must be even");
2509 Reg, RISCV::sub_gpr_even,
2510 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2511 Operands.push_back(RISCVOperand::createReg(Pair, S,
E));
2518 "operand must be a valid floating point rounding mode mnemonic");
2520 StringRef Str = getLexer().getTok().getIdentifier();
2525 "operand must be a valid floating point rounding mode mnemonic");
2527 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2533 const AsmToken &Tok = getLexer().getTok();
2539 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2553 for (
char c : Str) {
2582 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2588 return TokError(
"operand must be formed of letters selected in-order from "
2595 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2597 if (!parseRegister(
Operands).isSuccess())
2598 return Error(getLoc(),
"expected register");
2602 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2626 std::unique_ptr<RISCVOperand> OptionalImmOp;
2633 SMLoc ImmStart = getLoc();
2634 if (getParser().parseIntToken(ImmVal,
2635 "expected '(' or optional integer offset"))
2640 SMLoc ImmEnd = getLoc();
2643 ImmStart, ImmEnd, isRV64());
2647 OptionalImmOp ?
"expected '(' after optional integer offset"
2648 :
"expected '(' or optional integer offset"))
2651 if (!parseRegister(
Operands).isSuccess())
2652 return Error(getLoc(),
"expected register");
2658 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2660 OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2661 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2674 return Error(getLoc(),
"invalid register");
2681 return Error(getLoc(),
"expected register");
2683 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2686 return Error(getLoc(),
"invalid register");
2692 Operands.push_back(RISCVOperand::createRegReg(
Reg, Reg2, getLoc()));
2705 bool IsEABI = isRVE();
2708 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2713 if (RegStart != RISCV::X1)
2714 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2720 return Error(getLoc(),
"invalid register");
2724 return Error(getLoc(),
"invalid register");
2725 if (RegStart != RISCV::X8)
2726 return Error(getLoc(),
2727 "continuous register list must start from 's0' or 'x8'");
2733 StringRef EndName = getLexer().getTok().getIdentifier();
2737 return Error(getLoc(),
"invalid register");
2738 if (IsEABI && RegEnd != RISCV::X9)
2739 return Error(getLoc(),
"contiguous register list of EABI can only be "
2740 "'s0-s1' or 'x8-x9' pair");
2747 if (RegEnd != RISCV::X9)
2750 "first contiguous registers pair of register list must be 'x8-x9'");
2754 return Error(getLoc(),
"invalid register");
2755 StringRef EndName = getLexer().getTok().getIdentifier();
2757 return Error(getLoc(),
2758 "second contiguous registers pair of register list "
2759 "must start from 'x18'");
2765 return Error(getLoc(),
"invalid register");
2766 EndName = getLexer().getTok().getIdentifier();
2768 return Error(getLoc(),
"invalid register");
2775 if (RegEnd == RISCV::X26)
2776 return Error(getLoc(),
"invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2777 "x18-x26} is not supported");
2787 return Error(S,
"invalid register list");
2788 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2794 bool ExpectNegative) {
2800 unsigned RlistVal =
static_cast<RISCVOperand *
>(
Operands[1].get())->Rlist.Val;
2802 if (Negative != ExpectNegative ||
2805 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2817 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2824 if (parseRegister(
Operands,
true).isSuccess())
2831 return !parseMemOpBaseReg(
Operands).isSuccess();
2836 Error(getLoc(),
"unknown operand");
2849 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2850 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2851 if (Assembler !=
nullptr) {
2859 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2878 if (getParser().parseEOL(
"unexpected token")) {
2879 getParser().eatToEndOfStatement();
2885bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2889 if (
const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2890 Kind = RE->getKind();
2891 Expr = RE->getSubExpr();
2901bool RISCVAsmParser::isSymbolDiff(
const MCExpr *Expr) {
2914 if (IDVal ==
".option")
2915 return parseDirectiveOption();
2916 if (IDVal ==
".attribute")
2917 return parseDirectiveAttribute();
2918 if (IDVal ==
".insn")
2919 return parseDirectiveInsn(DirectiveID.
getLoc());
2920 if (IDVal ==
".variant_cc")
2921 return parseDirectiveVariantCC();
2926bool RISCVAsmParser::resetToArch(
StringRef Arch,
SMLoc Loc, std::string &Result,
2927 bool FromOptionDirective) {
2930 clearFeatureBits(Feature.Value, Feature.Key);
2939 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
2940 << ErrMsg.getMessage();
2943 return Error(Loc, OutputErrMsg.str());
2948 if (ISAInfo->hasExtension(Feature.Key))
2949 setFeatureBits(Feature.Value, Feature.Key);
2951 if (FromOptionDirective) {
2952 if (ISAInfo->getXLen() == 32 && isRV64())
2953 return Error(Loc,
"bad arch string switching from rv64 to rv32");
2954 else if (ISAInfo->getXLen() == 64 && !isRV64())
2955 return Error(Loc,
"bad arch string switching from rv32 to rv64");
2958 if (ISAInfo->getXLen() == 32)
2959 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
2960 else if (ISAInfo->getXLen() == 64)
2961 setFeatureBits(RISCV::Feature64Bit,
"64bit");
2963 return Error(Loc,
"bad arch string " + Arch);
2965 Result = ISAInfo->toString();
2969bool RISCVAsmParser::parseDirectiveOption() {
2980 if (Option ==
"push") {
2984 getTargetStreamer().emitDirectiveOptionPush();
2989 if (Option ==
"pop") {
2994 getTargetStreamer().emitDirectiveOptionPop();
2995 if (popFeatureBits())
2996 return Error(StartLoc,
".option pop with no .option push");
3001 if (Option ==
"arch") {
3009 Type = RISCVOptionArchArgType::Plus;
3011 Type = RISCVOptionArchArgType::Minus;
3012 else if (!
Args.empty())
3014 "unexpected token, expected + or -");
3016 Type = RISCVOptionArchArgType::Full;
3020 "unexpected token, expected identifier");
3026 if (
Type == RISCVOptionArchArgType::Full) {
3028 if (resetToArch(Arch, Loc, Result,
true))
3037 Loc,
"extension version number parsing not currently implemented");
3040 if (!enableExperimentalExtension() &&
3042 return Error(Loc,
"unexpected experimental extensions");
3045 return Error(Loc,
"unknown extension feature");
3049 if (
Type == RISCVOptionArchArgType::Plus) {
3052 setFeatureBits(
Ext->Value,
Ext->Key);
3055 copySTI().setFeatureBits(OldFeatureBits);
3056 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
3061 OutputErrMsg << ErrMsg.getMessage();
3064 return Error(Loc, OutputErrMsg.str());
3067 assert(
Type == RISCVOptionArchArgType::Minus);
3072 if (getSTI().hasFeature(Feature.Value) &&
3073 Feature.Implies.test(
Ext->Value))
3075 " extension; " + Feature.Key +
3076 " extension requires " +
Ext->Key +
3080 clearFeatureBits(
Ext->Value,
Ext->Key);
3087 getTargetStreamer().emitDirectiveOptionArch(Args);
3091 if (Option ==
"rvc") {
3095 getTargetStreamer().emitDirectiveOptionRVC();
3096 setFeatureBits(RISCV::FeatureStdExtC,
"c");
3100 if (Option ==
"norvc") {
3104 getTargetStreamer().emitDirectiveOptionNoRVC();
3105 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
3106 clearFeatureBits(RISCV::FeatureStdExtZca,
"zca");
3110 if (Option ==
"pic") {
3114 getTargetStreamer().emitDirectiveOptionPIC();
3115 ParserOptions.IsPicEnabled =
true;
3119 if (Option ==
"nopic") {
3123 getTargetStreamer().emitDirectiveOptionNoPIC();
3124 ParserOptions.IsPicEnabled =
false;
3128 if (Option ==
"relax") {
3132 getTargetStreamer().emitDirectiveOptionRelax();
3133 setFeatureBits(RISCV::FeatureRelax,
"relax");
3137 if (Option ==
"norelax") {
3141 getTargetStreamer().emitDirectiveOptionNoRelax();
3142 clearFeatureBits(RISCV::FeatureRelax,
"relax");
3148 "'rvc', 'norvc', 'arch', 'relax' or "
3157bool RISCVAsmParser::parseDirectiveAttribute() {
3164 std::optional<unsigned>
Ret =
3167 return Error(TagLoc,
"attribute name not recognised: " +
Name);
3178 if (check(!CE, TagLoc,
"expected numeric constant"))
3181 Tag =
CE->getValue();
3188 int64_t IntegerValue = 0;
3189 bool IsIntegerValue =
true;
3194 IsIntegerValue =
false;
3197 if (IsIntegerValue) {
3204 return Error(ValueExprLoc,
"expected numeric constant");
3205 IntegerValue =
CE->getValue();
3218 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3220 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3223 if (resetToArch(StringValue, ValueExprLoc, Result,
false))
3227 getTargetStreamer().emitTextAttribute(Tag, Result);
3235 .
Cases(
"r",
"r4",
"i",
"b",
"sb",
"u",
"j",
"uj",
"s",
true)
3236 .
Cases(
"cr",
"ci",
"ciw",
"css",
"cl",
"cs",
"ca",
"cb",
"cj", AllowC)
3244bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
3247 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3248 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3255 std::optional<int64_t>
Length;
3265 return Error(ErrorLoc,
3266 "instruction lengths must be a non-zero multiple of two");
3270 return Error(ErrorLoc,
3271 "instruction lengths over 64 bits are not supported");
3277 int64_t EncodingDerivedLength = ((
Value & 0b11) == 0b11) ? 4 : 2;
3282 if ((*
Length <= 4) && (*
Length != EncodingDerivedLength))
3283 return Error(ErrorLoc,
3284 "instruction length does not match the encoding");
3287 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3290 return Error(ErrorLoc,
"encoding value does not fit into instruction");
3293 if (!AllowC && (EncodingDerivedLength == 2))
3294 return Error(ErrorLoc,
"compressed instructions are not allowed");
3296 if (getParser().parseEOL(
"invalid operand for instruction")) {
3297 getParser().eatToEndOfStatement();
3305 Opcode = RISCV::Insn16;
3308 Opcode = RISCV::Insn32;
3311 Opcode = RISCV::Insn48;
3314 Opcode = RISCV::Insn64;
3320 Opcode = (EncodingDerivedLength == 2) ? RISCV::Insn16 : RISCV::Insn32;
3327 return Error(ErrorLoc,
"invalid instruction format");
3329 std::string FormatName = (
".insn_" +
Format).str();
3346bool RISCVAsmParser::parseDirectiveVariantCC() {
3348 if (getParser().parseIdentifier(
Name))
3349 return TokError(
"expected symbol name");
3352 getTargetStreamer().emitDirectiveVariantCC(
3353 *getContext().getOrCreateSymbol(
Name));
3361 ++RISCVNumInstrsCompressed;
3370 for (
MCInst &Inst : Seq) {
3371 emitToStreamer(Out, Inst);
3378 unsigned SecondOpcode,
SMLoc IDLoc,
3392 const MCExpr *RefToLinkTmpLabel =
3399 .addExpr(RefToLinkTmpLabel));
3402void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
3413 RISCV::ADDI, IDLoc, Out);
3416void RISCVAsmParser::emitLoadGlobalAddress(
MCInst &Inst,
SMLoc IDLoc,
3426 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3428 SecondOpcode, IDLoc, Out);
3431void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
3440 if (ParserOptions.IsPicEnabled)
3441 emitLoadGlobalAddress(Inst, IDLoc, Out);
3443 emitLoadLocalAddress(Inst, IDLoc, Out);
3446void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
3456 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3458 SecondOpcode, IDLoc, Out);
3461void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
3472 RISCV::ADDI, IDLoc, Out);
3475void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
3485 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3487 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3491 Opcode, IDLoc, Out);
3494void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
3495 int64_t Width,
SMLoc IDLoc,
3507 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3508 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3510 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
3523void RISCVAsmParser::emitVMSGE(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
3547 "The destination register should not be V0.");
3566 "The destination register should be V0.");
3568 "The temporary vector register should not be V0.");
3587 "The temporary vector register should not be V0.");
3612bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
3614 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
3617 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3618 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
3619 "%tprel_add modifier");
3625bool RISCVAsmParser::checkPseudoTLSDESCCall(
MCInst &Inst,
3627 assert(Inst.
getOpcode() == RISCV::PseudoTLSDESCCall &&
"Invalid instruction");
3630 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3631 return Error(ErrorLoc,
"the output operand must be t0/x5 when using "
3632 "%tlsdesc_call modifier");
3638std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
3642std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
3643 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3647std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp()
const {
3648 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3652bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
3656 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3657 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3660 if (DestReg == TempReg) {
3662 return Error(Loc,
"the temporary vector register cannot be the same as "
3663 "the destination register");
3667 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3668 Opcode == RISCV::TH_LWD) {
3673 if (Rs1 == Rd1 && Rs1 == Rd2) {
3675 return Error(Loc,
"rs1, rd1, and rd2 cannot all be the same");
3679 if (Opcode == RISCV::CM_MVSA01) {
3684 return Error(Loc,
"rs1 and rs2 must be different");
3688 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3689 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3690 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3695 return Error(Loc,
"operand must be constant 3");
3698 return Error(Loc,
"operand must be constant 4");
3705 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3706 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3712 if (VCIXDst == VCIXRs1)
3713 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3714 " overlap the source vector register group");
3718 if (VCIXDst == VCIXRs2)
3719 return Error(VCIXDstLoc,
"the destination vector register group cannot"
3720 " overlap the source vector register group");
3735 if (DestReg == CheckReg)
3736 return Error(Loc,
"the destination vector register group cannot overlap"
3737 " the source vector register group");
3741 if (DestReg == CheckReg)
3742 return Error(Loc,
"the destination vector register group cannot overlap"
3743 " the source vector register group");
3748 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3749 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3750 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3751 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3752 Opcode == RISCV::VMERGE_VXM)
3753 return Error(Loc,
"the destination vector register group cannot be V0");
3760 assert((CheckReg == RISCV::V0 || !CheckReg) &&
3761 "Unexpected register for mask operand");
3763 if (DestReg == CheckReg)
3764 return Error(Loc,
"the destination vector register group cannot overlap"
3765 " the mask register");
3770bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
3778 case RISCV::PseudoC_ADDI_NOP:
3781 case RISCV::PseudoLLAImm:
3782 case RISCV::PseudoLAImm:
3783 case RISCV::PseudoLI: {
3800 Imm = SignExtend64<32>(Imm);
3801 emitLoadImm(
Reg, Imm, Out);
3804 case RISCV::PseudoLLA:
3805 emitLoadLocalAddress(Inst, IDLoc, Out);
3807 case RISCV::PseudoLGA:
3808 emitLoadGlobalAddress(Inst, IDLoc, Out);
3810 case RISCV::PseudoLA:
3811 emitLoadAddress(Inst, IDLoc, Out);
3813 case RISCV::PseudoLA_TLS_IE:
3814 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3816 case RISCV::PseudoLA_TLS_GD:
3817 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3819 case RISCV::PseudoLB:
3820 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
3822 case RISCV::PseudoLBU:
3823 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
3825 case RISCV::PseudoLH:
3826 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
3828 case RISCV::PseudoLHU:
3829 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
3831 case RISCV::PseudoLW:
3832 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
3834 case RISCV::PseudoLWU:
3835 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
3837 case RISCV::PseudoLD:
3838 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
3840 case RISCV::PseudoFLH:
3841 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
3843 case RISCV::PseudoFLW:
3844 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
3846 case RISCV::PseudoFLD:
3847 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
3849 case RISCV::PseudoSB:
3850 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
3852 case RISCV::PseudoSH:
3853 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
3855 case RISCV::PseudoSW:
3856 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
3858 case RISCV::PseudoSD:
3859 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
3861 case RISCV::PseudoFSH:
3862 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
3864 case RISCV::PseudoFSW:
3865 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
3867 case RISCV::PseudoFSD:
3868 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
3870 case RISCV::PseudoAddTPRel:
3871 if (checkPseudoAddTPRel(Inst,
Operands))
3874 case RISCV::PseudoTLSDESCCall:
3875 if (checkPseudoTLSDESCCall(Inst,
Operands))
3878 case RISCV::PseudoSEXT_B:
3879 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
3881 case RISCV::PseudoSEXT_H:
3882 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
3884 case RISCV::PseudoZEXT_H:
3885 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
3887 case RISCV::PseudoZEXT_W:
3888 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
3890 case RISCV::PseudoVMSGEU_VX:
3891 case RISCV::PseudoVMSGEU_VX_M:
3892 case RISCV::PseudoVMSGEU_VX_M_T:
3893 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3895 case RISCV::PseudoVMSGE_VX:
3896 case RISCV::PseudoVMSGE_VX_M:
3897 case RISCV::PseudoVMSGE_VX_M_T:
3898 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3900 case RISCV::PseudoVMSGE_VI:
3901 case RISCV::PseudoVMSLT_VI: {
3905 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3915 case RISCV::PseudoVMSGEU_VI:
3916 case RISCV::PseudoVMSLTU_VI: {
3923 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3934 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3949 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.