47#define DEBUG_TYPE "riscv-asm-parser"
50 "Number of RISC-V Compressed instructions emitted");
62struct ParserOptionsSet {
74 VTypeState_TailPolicy,
75 VTypeState_MaskPolicy,
82 ParserOptionsSet ParserOptions;
90 "do not have a target streamer");
96 unsigned Kind)
override;
102 bool generateImmOutOfRangeError(
SMLoc ErrorLoc, int64_t
Lower, int64_t
Upper,
108 bool MatchingInlineAsm)
override;
112 SMLoc &EndLoc)
override;
119 bool parseVTypeToken(
StringRef Identifier, VTypeState &State,
unsigned &Sew,
120 unsigned &Lmul,
bool &Fractional,
bool &TailAgnostic,
122 bool generateVTypeError(
SMLoc ErrorLoc);
160 void emitPseudoExtend(
MCInst &Inst,
bool SignExtend, int64_t Width,
183#define GET_ASSEMBLER_HEADER
184#include "RISCVGenAsmMatcher.inc"
211 bool parseDirectiveOption();
212 bool parseDirectiveAttribute();
213 bool parseDirectiveInsn(
SMLoc L);
214 bool parseDirectiveVariantCC();
220 bool FromOptionDirective);
223 if (!(
getSTI().hasFeature(Feature))) {
231 if (
getSTI().hasFeature(Feature)) {
238 void pushFeatureBits() {
240 "These two stacks must be kept synchronized");
242 ParserOptionsStack.
push_back(ParserOptions);
245 bool popFeatureBits() {
247 "These two stacks must be kept synchronized");
248 if (FeatureBitStack.
empty())
260 std::unique_ptr<RISCVOperand> defaultMaskRegOp()
const;
261 std::unique_ptr<RISCVOperand> defaultFRMArgOp()
const;
262 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp()
const;
265 enum RISCVMatchResultTy {
267 Match_RequiresEvenGPRs,
268#define GET_OPERAND_DIAGNOSTIC_TYPES
269#include "RISCVGenAsmMatcher.inc"
270#undef GET_OPERAND_DIAGNOSTIC_TYPES
273 static bool classifySymbolRef(
const MCExpr *Expr,
275 static bool isSymbolDiff(
const MCExpr *Expr);
289 if (ABIName.endswith(
"f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
290 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
291 "doesn't support the F instruction set extension (ignoring "
293 }
else if (ABIName.endswith(
"d") &&
294 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
295 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
296 "doesn't support the D instruction set extension (ignoring "
309 getTargetStreamer().emitTargetAttributes(STI,
false);
378 SMLoc StartLoc, EndLoc;
384 struct SysRegOp SysReg;
385 struct VTypeOp VType;
387 struct FenceOp Fence;
388 struct RlistOp Rlist;
389 struct SpimmOp Spimm;
393 RISCVOperand(KindTy K) :
Kind(
K) {}
398 StartLoc =
o.StartLoc;
401 case KindTy::Register:
404 case KindTy::Immediate:
407 case KindTy::FPImmediate:
413 case KindTy::SystemRegister:
437 bool isToken()
const override {
return Kind == KindTy::Token; }
438 bool isReg()
const override {
return Kind == KindTy::Register; }
439 bool isV0Reg()
const {
440 return Kind == KindTy::Register &&
Reg.RegNum == RISCV::V0;
442 bool isAnyReg()
const {
443 return Kind == KindTy::Register &&
444 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum) ||
445 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg.RegNum) ||
446 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg.RegNum));
448 bool isAnyRegC()
const {
449 return Kind == KindTy::Register &&
450 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
452 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
455 bool isImm()
const override {
return Kind == KindTy::Immediate; }
456 bool isMem()
const override {
return false; }
457 bool isSystemRegister()
const {
return Kind == KindTy::SystemRegister; }
458 bool isRegReg()
const {
return Kind == KindTy::RegReg; }
459 bool isRlist()
const {
return Kind == KindTy::Rlist; }
460 bool isSpimm()
const {
return Kind == KindTy::Spimm; }
463 return Kind == KindTy::Register &&
464 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum);
467 bool isGPRAsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
469 bool isGPRF64AsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
471 bool isGPRPF64AsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
473 static bool evaluateConstantImm(
const MCExpr *Expr, int64_t &Imm,
475 if (
auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
477 return RE->evaluateAsConstant(Imm);
480 if (
auto CE = dyn_cast<MCConstantExpr>(Expr)) {
482 Imm =
CE->getValue();
491 template <
int N>
bool isBareSimmNLsb0()
const {
496 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
499 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
507 bool isBareSymbol()
const {
511 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
513 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
517 bool isCallSymbol()
const {
521 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
523 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
528 bool isPseudoJumpSymbol()
const {
532 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
534 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
538 bool isTPRelAddSymbol()
const {
542 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
544 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
548 bool isCSRSystemRegister()
const {
return isSystemRegister(); }
550 bool isVTypeImm(
unsigned N)
const {
555 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
561 bool isVTypeI10()
const {
562 if (Kind == KindTy::Immediate)
563 return isVTypeImm(10);
564 return Kind == KindTy::VType;
566 bool isVTypeI11()
const {
567 if (Kind == KindTy::Immediate)
568 return isVTypeImm(11);
569 return Kind == KindTy::VType;
574 bool isFenceArg()
const {
return Kind == KindTy::Fence; }
577 bool isFRMArg()
const {
return Kind == KindTy::FRM; }
578 bool isFRMArgLegacy()
const {
return Kind == KindTy::FRM; }
582 bool isLoadFPImm()
const {
585 if (Kind != KindTy::FPImmediate)
588 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
591 return Idx >= 0 &&
Idx != 1;
594 bool isImmXLenLI()
const {
599 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
606 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
609 return RISCVAsmParser::isSymbolDiff(getImm());
612 bool isImmXLenLI_Restricted()
const {
617 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
620 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
623 bool isUImmLog2XLen()
const {
628 if (!evaluateConstantImm(getImm(), Imm, VK) ||
631 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
634 bool isUImmLog2XLenNonZero()
const {
639 if (!evaluateConstantImm(getImm(), Imm, VK) ||
644 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
647 bool isUImmLog2XLenHalf()
const {
652 if (!evaluateConstantImm(getImm(), Imm, VK) ||
655 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
658 template <
unsigned N>
bool IsUImm()
const {
663 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
667 bool isUImm1()
const {
return IsUImm<1>(); }
668 bool isUImm2()
const {
return IsUImm<2>(); }
669 bool isUImm3()
const {
return IsUImm<3>(); }
670 bool isUImm4()
const {
return IsUImm<4>(); }
671 bool isUImm5()
const {
return IsUImm<5>(); }
672 bool isUImm6()
const {
return IsUImm<6>(); }
673 bool isUImm7()
const {
return IsUImm<7>(); }
674 bool isUImm8()
const {
return IsUImm<8>(); }
675 bool isUImm20()
const {
return IsUImm<20>(); }
677 bool isUImm8GE32()
const {
682 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
683 return IsConstantImm && isUInt<8>(Imm) &&
Imm >= 32 &&
687 bool isRnumArg()
const {
692 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
693 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(10) &&
697 bool isRnumArg_0_7()
const {
702 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
703 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(7) &&
707 bool isRnumArg_1_10()
const {
712 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
713 return IsConstantImm &&
Imm >= INT64_C(1) &&
Imm <= INT64_C(10) &&
717 bool isRnumArg_2_14()
const {
722 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
723 return IsConstantImm &&
Imm >= INT64_C(2) &&
Imm <= INT64_C(14) &&
727 bool isSImm5()
const {
732 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
733 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
737 bool isSImm6()
const {
742 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
743 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
747 bool isSImm6NonZero()
const {
752 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
753 return IsConstantImm &&
Imm != 0 &&
754 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
758 bool isCLUIImm()
const {
763 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
764 return IsConstantImm && (
Imm != 0) &&
765 (isUInt<5>(Imm) || (
Imm >= 0xfffe0 &&
Imm <= 0xfffff)) &&
769 bool isUImm2Lsb0()
const {
774 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
775 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
779 bool isUImm7Lsb00()
const {
784 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
785 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
789 bool isUImm8Lsb00()
const {
794 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
795 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
799 bool isUImm8Lsb000()
const {
804 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
805 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
809 bool isSImm9Lsb0()
const {
return isBareSimmNLsb0<9>(); }
811 bool isUImm9Lsb000()
const {
816 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
817 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
821 bool isUImm10Lsb00NonZero()
const {
826 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
827 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (
Imm != 0) &&
833 static int64_t fixImmediateForRV32(int64_t Imm,
bool IsRV64Imm) {
834 if (IsRV64Imm || !isUInt<32>(Imm))
836 return SignExtend64<32>(Imm);
839 bool isSImm12()
const {
845 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
847 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
849 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
856 bool isSImm12Lsb0()
const {
return isBareSimmNLsb0<12>(); }
858 bool isSImm12Lsb00000()
const {
863 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
864 return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
868 bool isSImm13Lsb0()
const {
return isBareSimmNLsb0<13>(); }
870 bool isSImm10Lsb0000NonZero()
const {
875 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
876 return IsConstantImm && (
Imm != 0) && isShiftedInt<6, 4>(Imm) &&
880 bool isUImm20LUI()
const {
886 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
887 if (!IsConstantImm) {
888 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
898 bool isUImm20AUIPC()
const {
904 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
905 if (!IsConstantImm) {
906 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
920 bool isSImm21Lsb0JAL()
const {
return isBareSimmNLsb0<21>(); }
922 bool isImmZero()
const {
927 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
931 bool isSImm5Plus1()
const {
936 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
937 return IsConstantImm &&
938 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
943 SMLoc getStartLoc()
const override {
return StartLoc; }
945 SMLoc getEndLoc()
const override {
return EndLoc; }
947 bool isRV64Imm()
const {
948 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
952 unsigned getReg()
const override {
953 assert(Kind == KindTy::Register &&
"Invalid type access!");
954 return Reg.RegNum.id();
958 assert(Kind == KindTy::SystemRegister &&
"Invalid type access!");
959 return StringRef(SysReg.Data, SysReg.Length);
962 const MCExpr *getImm()
const {
963 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
968 assert(Kind == KindTy::FPImmediate &&
"Invalid type access!");
973 assert(Kind == KindTy::Token &&
"Invalid type access!");
977 unsigned getVType()
const {
978 assert(Kind == KindTy::VType &&
"Invalid type access!");
983 assert(Kind == KindTy::FRM &&
"Invalid type access!");
987 unsigned getFence()
const {
988 assert(Kind == KindTy::Fence &&
"Invalid type access!");
1001 case KindTy::Immediate:
1004 case KindTy::FPImmediate:
1006 case KindTy::Register:
1010 OS <<
"'" << getToken() <<
"'";
1012 case KindTy::SystemRegister:
1013 OS <<
"<sysreg: " << getSysReg() <<
'>';
1022 roundingModeToString(getFRM());
1040 case KindTy::RegReg:
1047 static std::unique_ptr<RISCVOperand> createToken(
StringRef Str,
SMLoc S) {
1048 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1055 static std::unique_ptr<RISCVOperand>
1056 createReg(
unsigned RegNo,
SMLoc S,
SMLoc E,
bool IsGPRAsFPR =
false) {
1057 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1058 Op->Reg.RegNum = RegNo;
1059 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1065 static std::unique_ptr<RISCVOperand> createImm(
const MCExpr *Val,
SMLoc S,
1067 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1069 Op->Imm.IsRV64 = IsRV64;
1075 static std::unique_ptr<RISCVOperand> createFPImm(
uint64_t Val,
SMLoc S) {
1076 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1077 Op->FPImm.Val = Val;
1083 static std::unique_ptr<RISCVOperand> createSysReg(
StringRef Str,
SMLoc S,
1084 unsigned Encoding) {
1085 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1086 Op->SysReg.Data = Str.data();
1087 Op->SysReg.Length = Str.size();
1094 static std::unique_ptr<RISCVOperand>
1096 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1103 static std::unique_ptr<RISCVOperand> createFenceArg(
unsigned Val,
SMLoc S) {
1104 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1105 Op->Fence.Val = Val;
1111 static std::unique_ptr<RISCVOperand> createVType(
unsigned VTypeI,
SMLoc S) {
1112 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1113 Op->VType.Val = VTypeI;
1119 static std::unique_ptr<RISCVOperand> createRlist(
unsigned RlistEncode,
1121 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1122 Op->Rlist.Val = RlistEncode;
1127 static std::unique_ptr<RISCVOperand> createRegReg(
unsigned Reg1No,
1128 unsigned Reg2No,
SMLoc S) {
1129 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1130 Op->RegReg.Reg1 = Reg1No;
1131 Op->RegReg.Reg2 = Reg2No;
1137 static std::unique_ptr<RISCVOperand> createSpimm(
unsigned Spimm,
SMLoc S) {
1138 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1139 Op->Spimm.Val = Spimm;
1144 static void addExpr(
MCInst &Inst,
const MCExpr *Expr,
bool IsRV64Imm) {
1145 assert(Expr &&
"Expr shouldn't be null!");
1148 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1158 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
1159 assert(
N == 1 &&
"Invalid number of operands!");
1163 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
1164 assert(
N == 1 &&
"Invalid number of operands!");
1165 addExpr(Inst, getImm(), isRV64Imm());
1168 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
1169 assert(
N == 1 &&
"Invalid number of operands!");
1171 addExpr(Inst, getImm(), isRV64Imm());
1176 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
1180 void addFenceArgOperands(
MCInst &Inst,
unsigned N)
const {
1181 assert(
N == 1 &&
"Invalid number of operands!");
1185 void addCSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
1186 assert(
N == 1 &&
"Invalid number of operands!");
1193 void addVTypeIOperands(
MCInst &Inst,
unsigned N)
const {
1194 assert(
N == 1 &&
"Invalid number of operands!");
1196 if (Kind == KindTy::Immediate) {
1198 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1199 (void)IsConstantImm;
1200 assert(IsConstantImm &&
"Invalid VTypeI Operand!");
1207 void addRlistOperands(
MCInst &Inst,
unsigned N)
const {
1208 assert(
N == 1 &&
"Invalid number of operands!");
1212 void addRegRegOperands(
MCInst &Inst,
unsigned N)
const {
1213 assert(
N == 1 &&
"Invalid number of operands!");
1218 void addSpimmOperands(
MCInst &Inst,
unsigned N)
const {
1219 assert(
N == 1 &&
"Invalid number of operands!");
1223 void addFRMArgOperands(
MCInst &Inst,
unsigned N)
const {
1224 assert(
N == 1 &&
"Invalid number of operands!");
1230#define GET_REGISTER_MATCHER
1231#define GET_SUBTARGET_FEATURE_NAME
1232#define GET_MATCHER_IMPLEMENTATION
1233#define GET_MNEMONIC_SPELL_CHECKER
1234#include "RISCVGenAsmMatcher.inc"
1237 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1238 return Reg - RISCV::F0_D + RISCV::F0_H;
1242 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1243 return Reg - RISCV::F0_D + RISCV::F0_F;
1248 unsigned RegClassID;
1249 if (Kind == MCK_VRM2)
1250 RegClassID = RISCV::VRM2RegClassID;
1251 else if (Kind == MCK_VRM4)
1252 RegClassID = RISCV::VRM4RegClassID;
1253 else if (Kind == MCK_VRM8)
1254 RegClassID = RISCV::VRM8RegClassID;
1258 &RISCVMCRegisterClasses[RegClassID]);
1263 RISCVOperand &
Op =
static_cast<RISCVOperand &
>(AsmOp);
1265 return Match_InvalidOperand;
1269 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg);
1271 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
Reg);
1272 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg);
1276 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1277 (IsRegFPR64C &&
Kind == MCK_FPR32C)) {
1279 return Match_Success;
1283 if (IsRegFPR64 && Kind == MCK_FPR16) {
1285 return Match_Success;
1289 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1291 if (
Op.Reg.RegNum == 0)
1292 return Match_InvalidOperand;
1293 return Match_Success;
1295 return Match_InvalidOperand;
1298unsigned RISCVAsmParser::checkTargetMatchPredicate(
MCInst &Inst) {
1302 if (MCID.
operands()[
I].RegClass == RISCV::GPRPF64RegClassID) {
1307 if (((
Reg.id() - RISCV::X0) & 1) != 0)
1308 return Match_RequiresEvenGPRs;
1312 return Match_Success;
1315bool RISCVAsmParser::generateImmOutOfRangeError(
1317 const Twine &Msg =
"immediate must be an integer in the range") {
1321bool RISCVAsmParser::generateImmOutOfRangeError(
1323 const Twine &Msg =
"immediate must be an integer in the range") {
1325 return generateImmOutOfRangeError(ErrorLoc,
Lower,
Upper, Msg);
1328bool RISCVAsmParser::MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &
Opcode,
1332 bool MatchingInlineAsm) {
1342 if (validateInstruction(Inst,
Operands))
1344 return processInstruction(Inst, IDLoc,
Operands, Out);
1345 case Match_MissingFeature: {
1346 assert(MissingFeatures.
any() &&
"Unknown missing features!");
1347 bool FirstFeature =
true;
1348 std::string
Msg =
"instruction requires the following:";
1349 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
1350 if (MissingFeatures[i]) {
1351 Msg += FirstFeature ?
" " :
", ";
1353 FirstFeature =
false;
1356 return Error(IDLoc, Msg);
1358 case Match_MnemonicFail: {
1359 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1360 std::string Suggestion = RISCVMnemonicSpellCheck(
1361 ((RISCVOperand &)*
Operands[0]).getToken(), FBS, 0);
1362 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
1364 case Match_InvalidOperand: {
1365 SMLoc ErrorLoc = IDLoc;
1368 return Error(ErrorLoc,
"too few operands for instruction");
1371 if (ErrorLoc ==
SMLoc())
1374 return Error(ErrorLoc,
"invalid operand for instruction");
1381 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1382 SMLoc ErrorLoc = IDLoc;
1384 return Error(ErrorLoc,
"too few operands for instruction");
1390 case Match_RequiresEvenGPRs:
1392 "double precision floating point operands must use even "
1393 "numbered X register");
1394 case Match_InvalidImmXLenLI:
1397 return Error(ErrorLoc,
"operand must be a constant 64-bit integer");
1400 std::numeric_limits<int32_t>::min(),
1401 std::numeric_limits<uint32_t>::max());
1402 case Match_InvalidImmXLenLI_Restricted:
1405 return Error(ErrorLoc,
"operand either must be a constant 64-bit integer "
1406 "or a bare symbol name");
1408 return generateImmOutOfRangeError(
1410 std::numeric_limits<uint32_t>::max(),
1411 "operand either must be a bare symbol name or an immediate integer in "
1413 case Match_InvalidImmZero: {
1415 return Error(ErrorLoc,
"immediate must be zero");
1417 case Match_InvalidUImmLog2XLen:
1421 case Match_InvalidUImmLog2XLenNonZero:
1425 case Match_InvalidUImmLog2XLenHalf:
1429 case Match_InvalidUImm1:
1431 case Match_InvalidUImm2:
1433 case Match_InvalidUImm2Lsb0:
1435 "immediate must be one of");
1436 case Match_InvalidUImm3:
1438 case Match_InvalidUImm4:
1440 case Match_InvalidUImm5:
1442 case Match_InvalidUImm6:
1444 case Match_InvalidUImm7:
1446 case Match_InvalidUImm8:
1448 case Match_InvalidUImm8GE32:
1450 case Match_InvalidSImm5:
1453 case Match_InvalidSImm6:
1456 case Match_InvalidSImm6NonZero:
1457 return generateImmOutOfRangeError(
1459 "immediate must be non-zero in the range");
1460 case Match_InvalidCLUIImm:
1461 return generateImmOutOfRangeError(
1463 "immediate must be in [0xfffe0, 0xfffff] or");
1464 case Match_InvalidUImm7Lsb00:
1465 return generateImmOutOfRangeError(
1467 "immediate must be a multiple of 4 bytes in the range");
1468 case Match_InvalidUImm8Lsb00:
1469 return generateImmOutOfRangeError(
1471 "immediate must be a multiple of 4 bytes in the range");
1472 case Match_InvalidUImm8Lsb000:
1473 return generateImmOutOfRangeError(
1475 "immediate must be a multiple of 8 bytes in the range");
1476 case Match_InvalidSImm9Lsb0:
1477 return generateImmOutOfRangeError(
1479 "immediate must be a multiple of 2 bytes in the range");
1480 case Match_InvalidUImm9Lsb000:
1481 return generateImmOutOfRangeError(
1483 "immediate must be a multiple of 8 bytes in the range");
1484 case Match_InvalidUImm10Lsb00NonZero:
1485 return generateImmOutOfRangeError(
1487 "immediate must be a multiple of 4 bytes in the range");
1488 case Match_InvalidSImm10Lsb0000NonZero:
1489 return generateImmOutOfRangeError(
1491 "immediate must be a multiple of 16 bytes and non-zero in the range");
1492 case Match_InvalidSImm12:
1493 return generateImmOutOfRangeError(
1495 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1496 "integer in the range");
1497 case Match_InvalidSImm12Lsb0:
1498 return generateImmOutOfRangeError(
1500 "immediate must be a multiple of 2 bytes in the range");
1501 case Match_InvalidSImm12Lsb00000:
1502 return generateImmOutOfRangeError(
1504 "immediate must be a multiple of 32 bytes in the range");
1505 case Match_InvalidSImm13Lsb0:
1506 return generateImmOutOfRangeError(
1508 "immediate must be a multiple of 2 bytes in the range");
1509 case Match_InvalidUImm20LUI:
1511 "operand must be a symbol with "
1512 "%hi/%tprel_hi modifier or an integer in "
1514 case Match_InvalidUImm20:
1516 case Match_InvalidUImm20AUIPC:
1517 return generateImmOutOfRangeError(
1519 "operand must be a symbol with a "
1520 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1521 "an integer in the range");
1522 case Match_InvalidSImm21Lsb0JAL:
1523 return generateImmOutOfRangeError(
1525 "immediate must be a multiple of 2 bytes in the range");
1526 case Match_InvalidCSRSystemRegister: {
1528 "operand must be a valid system register "
1529 "name or an integer in the range");
1531 case Match_InvalidLoadFPImm: {
1533 return Error(ErrorLoc,
"operand must be a valid floating-point constant");
1535 case Match_InvalidBareSymbol: {
1537 return Error(ErrorLoc,
"operand must be a bare symbol name");
1539 case Match_InvalidPseudoJumpSymbol: {
1541 return Error(ErrorLoc,
"operand must be a valid jump target");
1543 case Match_InvalidCallSymbol: {
1545 return Error(ErrorLoc,
"operand must be a bare symbol name");
1547 case Match_InvalidTPRelAddSymbol: {
1549 return Error(ErrorLoc,
"operand must be a symbol with %tprel_add modifier");
1551 case Match_InvalidRTZArg: {
1553 return Error(ErrorLoc,
"operand must be 'rtz' floating-point rounding mode");
1555 case Match_InvalidVTypeI: {
1557 return generateVTypeError(ErrorLoc);
1559 case Match_InvalidVMaskRegister: {
1561 return Error(ErrorLoc,
"operand must be v0.t");
1563 case Match_InvalidSImm5Plus1: {
1566 "immediate must be in the range");
1568 case Match_InvalidRlist: {
1572 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1574 case Match_InvalidSpimm: {
1578 "stack adjustment is invalid for this instruction and register list; "
1579 "refer to Zc spec for a detailed range of stack adjustment");
1581 case Match_InvalidRnumArg: {
1584 case Match_InvalidRegReg: {
1586 return Error(ErrorLoc,
"operands must be register and register");
1604 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1605 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1608 if (IsRVE &&
Reg >= RISCV::X16 &&
Reg <= RISCV::X31)
1609 Reg = RISCV::NoRegister;
1615 if (!tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess())
1616 return Error(StartLoc,
"invalid register name");
1622 const AsmToken &Tok = getParser().getTok();
1637 SMLoc FirstS = getLoc();
1638 bool HadParens =
false;
1645 size_t ReadCount = getLexer().peekTokens(Buf);
1648 LParen = getParser().getTok();
1653 switch (getLexer().getKind()) {
1656 getLexer().UnLex(LParen);
1664 getLexer().UnLex(LParen);
1668 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1672 Operands.push_back(RISCVOperand::createReg(RegNo, S,
E));
1677 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1688 switch (getLexer().getKind()) {
1698 if (getParser().parseExpression(Res,
E))
1701 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1703 int64_t
Imm =
CE->getValue();
1704 if (isUInt<7>(Imm)) {
1705 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1714 if (getParser().parseIdentifier(Identifier))
1717 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1720 "Unexpected opcode");
1723 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1733 return generateImmOutOfRangeError(
1735 "opcode must be a valid opcode name or an immediate in the range");
1743 switch (getLexer().getKind()) {
1753 if (getParser().parseExpression(Res,
E))
1756 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1758 int64_t
Imm =
CE->getValue();
1759 if (Imm >= 0 && Imm <= 2) {
1760 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1769 if (getParser().parseIdentifier(Identifier))
1773 if (Identifier ==
"C0")
1775 else if (Identifier ==
"C1")
1777 else if (Identifier ==
"C2")
1784 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1793 return generateImmOutOfRangeError(
1795 "opcode must be a valid opcode name or an immediate in the range");
1802 switch (getLexer().getKind()) {
1812 if (getParser().parseExpression(Res))
1815 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1817 int64_t
Imm =
CE->getValue();
1818 if (isUInt<12>(Imm)) {
1819 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1823 RISCVOperand::createSysReg(SysReg ? SysReg->Name :
"", S, Imm));
1828 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1832 if (getParser().parseIdentifier(Identifier))
1838 auto CheckCSRNameConflict = [&]() {
1839 if (!(RISCVSysReg::lookupSysRegByName(Identifier))) {
1840 Error(S,
"system register use requires an option to be enabled");
1847 auto SiFiveReg = RISCVSysReg::lookupSiFiveRegByName(Identifier);
1849 if (SiFiveReg->haveVendorRequiredFeatures(getSTI().getFeatureBits())) {
1851 RISCVOperand::createSysReg(Identifier, S, SiFiveReg->Encoding));
1854 if (CheckCSRNameConflict())
1858 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1860 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1861 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
1862 SysReg->Name +
"'");
1867 auto CheckCSREncodingConflict = [&]() {
1868 auto Reg = RISCVSysReg::lookupSiFiveRegByEncoding(SysReg->Encoding);
1869 if (
Reg &&
Reg->haveVendorRequiredFeatures(getSTI().getFeatureBits())) {
1870 Warning(S,
"'" + Identifier +
"' CSR is not available on the current " +
1871 "subtarget. Instead '" +
Reg->Name +
1872 "' CSR will be used.");
1874 RISCVOperand::createSysReg(
Reg->Name, S,
Reg->Encoding));
1882 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))
1883 return Error(S,
"system register use requires an option to be enabled");
1884 if (CheckCSREncodingConflict())
1887 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1891 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
1892 "operand must be a valid system register "
1893 "name or an integer in the range");
1897 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1910 if (
Identifier.compare_insensitive(
"inf") == 0) {
1913 getTok().getEndLoc(), isRV64()));
1914 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
1917 getTok().getEndLoc(), isRV64()));
1918 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
1921 getTok().getEndLoc(), isRV64()));
1923 return TokError(
"invalid floating point literal");
1936 return TokError(
"invalid floating point immediate");
1939 APFloat RealVal(APFloat::IEEEdouble());
1941 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
1943 return TokError(
"invalid floating point representation");
1946 RealVal.changeSign();
1948 Operands.push_back(RISCVOperand::createFPImm(
1949 RealVal.bitcastToAPInt().getZExtValue(), S));
1961 switch (getLexer().getKind()) {
1973 if (getParser().parseExpression(Res,
E))
1977 return parseOperandWithModifier(
Operands);
1980 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1992 return Error(getLoc(),
"expected valid identifier for operand modifier");
1996 return Error(getLoc(),
"unrecognized operand modifier");
2003 if (getParser().parseParenExpression(SubExpr,
E))
2007 Operands.push_back(RISCVOperand::createImm(ModExpr, S,
E, isRV64()));
2019 AsmToken Tok = getLexer().getTok();
2021 if (getParser().parseIdentifier(Identifier))
2027 return Error(getLoc(),
"'@plt' operand not valid for instruction");
2029 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2031 if (
Sym->isVariable()) {
2032 const MCExpr *
V =
Sym->getVariableValue(
false);
2033 if (!isa<MCSymbolRefExpr>(V)) {
2034 getLexer().UnLex(Tok);
2042 switch (getLexer().getKind()) {
2044 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2057 if (getParser().parseExpression(Expr,
E))
2060 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2076 if (getParser().parseIdentifier(Identifier))
2085 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2088 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2097 if (getParser().parseExpression(Res,
E))
2100 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef ||
2101 cast<MCSymbolRefExpr>(Res)->getKind() ==
2102 MCSymbolRefExpr::VariantKind::VK_PLT)
2103 return Error(S,
"operand must be a valid jump target");
2106 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2127bool RISCVAsmParser::parseVTypeToken(
StringRef Identifier, VTypeState &State,
2128 unsigned &Sew,
unsigned &Lmul,
2129 bool &Fractional,
bool &TailAgnostic,
2130 bool &MaskAgnostic) {
2132 case VTypeState_SEW:
2139 State = VTypeState_LMUL;
2141 case VTypeState_LMUL: {
2149 State = VTypeState_TailPolicy;
2152 case VTypeState_TailPolicy:
2153 if (Identifier ==
"ta")
2154 TailAgnostic =
true;
2155 else if (Identifier ==
"tu")
2156 TailAgnostic =
false;
2159 State = VTypeState_MaskPolicy;
2161 case VTypeState_MaskPolicy:
2162 if (Identifier ==
"ma")
2163 MaskAgnostic =
true;
2164 else if (Identifier ==
"mu")
2165 MaskAgnostic =
false;
2168 State = VTypeState_Done;
2170 case VTypeState_Done:
2183 bool Fractional =
false;
2184 bool TailAgnostic =
false;
2185 bool MaskAgnostic =
false;
2187 VTypeState State = VTypeState_SEW;
2194 if (parseVTypeToken(Identifier, State, Sew, Lmul, Fractional, TailAgnostic,
2206 if (parseVTypeToken(Identifier, State, Sew, Lmul, Fractional, TailAgnostic,
2218 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2222 return generateVTypeError(S);
2225bool RISCVAsmParser::generateVTypeError(
SMLoc ErrorLoc) {
2229 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2237 if (!
Name.consume_back(
".t"))
2238 return Error(getLoc(),
"expected '.t' suffix");
2243 if (RegNo != RISCV::V0)
2248 Operands.push_back(RISCVOperand::createReg(RegNo, S,
E));
2264 Operands.push_back(RISCVOperand::createReg(
2265 RegNo, S,
E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2272 "operand must be a valid floating point rounding mode mnemonic");
2274 StringRef Str = getLexer().getTok().getIdentifier();
2279 "operand must be a valid floating point rounding mode mnemonic");
2281 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2287 const AsmToken &Tok = getLexer().getTok();
2293 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2307 for (
char c : Str) {
2336 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2342 return TokError(
"operand must be formed of letters selected in-order from "
2349 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2351 if (!parseRegister(
Operands).isSuccess())
2352 return Error(getLoc(),
"expected register");
2356 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2380 std::unique_ptr<RISCVOperand> OptionalImmOp;
2387 SMLoc ImmStart = getLoc();
2388 if (getParser().parseIntToken(ImmVal,
2389 "expected '(' or optional integer offset"))
2394 SMLoc ImmEnd = getLoc();
2397 ImmStart, ImmEnd, isRV64());
2401 OptionalImmOp ?
"expected '(' after optional integer offset"
2402 :
"expected '(' or optional integer offset"))
2405 if (!parseRegister(
Operands).isSuccess())
2406 return Error(getLoc(),
"expected register");
2412 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2414 OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2415 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2428 return Error(getLoc(),
"invalid register");
2435 return Error(getLoc(),
"expected register");
2437 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2440 return Error(getLoc(),
"invalid register");
2446 Operands.push_back(RISCVOperand::createRegReg(
Reg, Reg2, getLoc()));
2459 bool IsEABI = isRVE();
2462 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2467 if (RegStart != RISCV::X1)
2468 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2474 return Error(getLoc(),
"invalid register");
2478 return Error(getLoc(),
"invalid register");
2479 if (RegStart != RISCV::X8)
2480 return Error(getLoc(),
2481 "continuous register list must start from 's0' or 'x8'");
2487 StringRef EndName = getLexer().getTok().getIdentifier();
2491 return Error(getLoc(),
"invalid register");
2492 if (IsEABI && RegEnd != RISCV::X9)
2493 return Error(getLoc(),
"contiguous register list of EABI can only be "
2494 "'s0-s1' or 'x8-x9' pair");
2501 if (RegEnd != RISCV::X9)
2504 "first contiguous registers pair of register list must be 'x8-x9'");
2508 return Error(getLoc(),
"invalid register");
2509 StringRef EndName = getLexer().getTok().getIdentifier();
2511 return Error(getLoc(),
2512 "second contiguous registers pair of register list "
2513 "must start from 'x18'");
2519 return Error(getLoc(),
"invalid register");
2520 EndName = getLexer().getTok().getIdentifier();
2522 return Error(getLoc(),
"invalid register");
2529 if (RegEnd == RISCV::X26)
2530 return Error(getLoc(),
"invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2531 "x18-x26} is not supported");
2536 if (RegEnd == RISCV::NoRegister)
2541 return Error(S,
"invalid register list");
2542 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2553 unsigned RlistVal =
static_cast<RISCVOperand *
>(
Operands[1].get())->Rlist.Val;
2555 bool IsEABI = isRVE();
2558 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2570 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2577 if (parseRegister(
Operands,
true).isSuccess())
2584 return !parseMemOpBaseReg(
Operands).isSuccess();
2589 Error(getLoc(),
"unknown operand");
2602 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2603 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2604 if (Assembler !=
nullptr) {
2612 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2631 if (getParser().parseEOL(
"unexpected token")) {
2632 getParser().eatToEndOfStatement();
2638bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2642 if (
const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2643 Kind = RE->getKind();
2644 Expr = RE->getSubExpr();
2654bool RISCVAsmParser::isSymbolDiff(
const MCExpr *Expr) {
2667 if (IDVal ==
".option")
2668 return parseDirectiveOption();
2669 if (IDVal ==
".attribute")
2670 return parseDirectiveAttribute();
2671 if (IDVal ==
".insn")
2672 return parseDirectiveInsn(DirectiveID.
getLoc());
2673 if (IDVal ==
".variant_cc")
2674 return parseDirectiveVariantCC();
2679bool RISCVAsmParser::resetToArch(
StringRef Arch,
SMLoc Loc, std::string &Result,
2680 bool FromOptionDirective) {
2683 clearFeatureBits(Feature.Value, Feature.Key);
2692 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
2693 << ErrMsg.getMessage();
2696 return Error(Loc, OutputErrMsg.str());
2698 auto &ISAInfo = *ParseResult;
2701 if (ISAInfo->hasExtension(Feature.Key))
2702 setFeatureBits(Feature.Value, Feature.Key);
2704 if (FromOptionDirective) {
2705 if (ISAInfo->getXLen() == 32 && isRV64())
2706 return Error(Loc,
"bad arch string switching from rv64 to rv32");
2707 else if (ISAInfo->getXLen() == 64 && !isRV64())
2708 return Error(Loc,
"bad arch string switching from rv32 to rv64");
2711 if (ISAInfo->getXLen() == 32)
2712 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
2713 else if (ISAInfo->getXLen() == 64)
2714 setFeatureBits(RISCV::Feature64Bit,
"64bit");
2716 return Error(Loc,
"bad arch string " + Arch);
2718 Result = ISAInfo->toString();
2722bool RISCVAsmParser::parseDirectiveOption() {
2733 if (Option ==
"push") {
2737 getTargetStreamer().emitDirectiveOptionPush();
2742 if (Option ==
"pop") {
2747 getTargetStreamer().emitDirectiveOptionPop();
2748 if (popFeatureBits())
2749 return Error(StartLoc,
".option pop with no .option push");
2754 if (Option ==
"arch") {
2762 Type = RISCVOptionArchArgType::Plus;
2764 Type = RISCVOptionArchArgType::Minus;
2765 else if (!
Args.empty())
2767 "unexpected token, expected + or -");
2769 Type = RISCVOptionArchArgType::Full;
2773 "unexpected token, expected identifier");
2779 if (
Type == RISCVOptionArchArgType::Full) {
2781 if (resetToArch(Arch, Loc, Result,
true))
2790 if (Ext == KVArray.end() ||
StringRef(
Ext->Key) != Arch ||
2795 "Extension version number parsing not currently implemented");
2796 return Error(Loc,
"unknown extension feature");
2801 if (
Type == RISCVOptionArchArgType::Plus) {
2804 setFeatureBits(
Ext->Value,
Ext->Key);
2807 copySTI().setFeatureBits(OldFeatureBits);
2808 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
2813 OutputErrMsg << ErrMsg.getMessage();
2816 return Error(Loc, OutputErrMsg.str());
2819 assert(
Type == RISCVOptionArchArgType::Minus);
2823 for (
auto Feature : KVArray) {
2824 if (getSTI().hasFeature(Feature.Value) &&
2825 Feature.Implies.test(
Ext->Value))
2827 Twine(
"Can't disable ") +
Ext->Key +
" extension, " +
2828 Feature.Key +
" extension requires " +
Ext->Key +
2829 " extension be enabled");
2832 clearFeatureBits(
Ext->Value,
Ext->Key);
2839 getTargetStreamer().emitDirectiveOptionArch(Args);
2843 if (Option ==
"rvc") {
2847 getTargetStreamer().emitDirectiveOptionRVC();
2848 setFeatureBits(RISCV::FeatureStdExtC,
"c");
2852 if (Option ==
"norvc") {
2856 getTargetStreamer().emitDirectiveOptionNoRVC();
2857 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
2858 clearFeatureBits(RISCV::FeatureStdExtZca,
"+zca");
2862 if (Option ==
"pic") {
2866 getTargetStreamer().emitDirectiveOptionPIC();
2867 ParserOptions.IsPicEnabled =
true;
2871 if (Option ==
"nopic") {
2875 getTargetStreamer().emitDirectiveOptionNoPIC();
2876 ParserOptions.IsPicEnabled =
false;
2880 if (Option ==
"relax") {
2884 getTargetStreamer().emitDirectiveOptionRelax();
2885 setFeatureBits(RISCV::FeatureRelax,
"relax");
2889 if (Option ==
"norelax") {
2893 getTargetStreamer().emitDirectiveOptionNoRelax();
2894 clearFeatureBits(RISCV::FeatureRelax,
"relax");
2900 "'rvc', 'norvc', 'arch', 'relax' or "
2909bool RISCVAsmParser::parseDirectiveAttribute() {
2916 std::optional<unsigned>
Ret =
2919 return Error(TagLoc,
"attribute name not recognised: " +
Name);
2930 if (
check(!CE, TagLoc,
"expected numeric constant"))
2933 Tag =
CE->getValue();
2940 int64_t IntegerValue = 0;
2941 bool IsIntegerValue =
true;
2946 IsIntegerValue =
false;
2949 if (IsIntegerValue) {
2956 return Error(ValueExprLoc,
"expected numeric constant");
2957 IntegerValue =
CE->getValue();
2970 getTargetStreamer().emitAttribute(
Tag, IntegerValue);
2972 getTargetStreamer().emitTextAttribute(
Tag, StringValue);
2975 if (resetToArch(StringValue, ValueExprLoc, Result,
false))
2979 getTargetStreamer().emitTextAttribute(
Tag, Result);
2987 .
Cases(
"r",
"r4",
"i",
"b",
"sb",
"u",
"j",
"uj",
"s",
true)
2988 .
Cases(
"cr",
"ci",
"ciw",
"css",
"cl",
"cs",
"ca",
"cb",
"cj", AllowC)
2994bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
3001 return Error(ErrorLoc,
"expected instruction format");
3003 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3004 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3006 return Error(ErrorLoc,
"invalid instruction format");
3008 std::string FormatName = (
".insn_" +
Format).str();
3025bool RISCVAsmParser::parseDirectiveVariantCC() {
3027 if (getParser().parseIdentifier(
Name))
3028 return TokError(
"expected symbol name");
3031 getTargetStreamer().emitDirectiveVariantCC(
3032 *getContext().getOrCreateSymbol(
Name));
3040 ++RISCVNumInstrsCompressed;
3050 switch (Inst.getOpndKind()) {
3080 unsigned SecondOpcode,
SMLoc IDLoc,
3094 const MCExpr *RefToLinkTmpLabel =
3101 .addExpr(RefToLinkTmpLabel));
3104void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
3115 RISCV::ADDI, IDLoc, Out);
3118void RISCVAsmParser::emitLoadGlobalAddress(
MCInst &Inst,
SMLoc IDLoc,
3128 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3130 SecondOpcode, IDLoc, Out);
3133void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
3142 if (ParserOptions.IsPicEnabled)
3143 emitLoadGlobalAddress(Inst, IDLoc, Out);
3145 emitLoadLocalAddress(Inst, IDLoc, Out);
3148void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
3158 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3160 SecondOpcode, IDLoc, Out);
3163void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
3174 RISCV::ADDI, IDLoc, Out);
3177void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
3187 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3189 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3196void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
3197 int64_t Width,
SMLoc IDLoc,
3209 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3210 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3212 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
3236 .addReg(RISCV::NoRegister));
3247 "The destination register should not be V0.");
3256 .addReg(RISCV::V0));
3264 "The destination register should be V0.");
3266 "The temporary vector register should not be V0.");
3271 .addReg(RISCV::NoRegister));
3283 "The temporary vector register should not be V0.");
3288 .addReg(RISCV::NoRegister));
3296 .addReg(RISCV::V0));
3304bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
3306 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
3309 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3310 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
3311 "%tprel_add modifier");
3317std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
3318 return RISCVOperand::createReg(RISCV::NoRegister,
llvm::SMLoc(),
3322std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
3323 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3327std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp()
const {
3328 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3332bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
3336 if (
Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3337 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3340 if (DestReg == TempReg) {
3342 return Error(Loc,
"The temporary vector register cannot be the same as "
3343 "the destination register.");
3347 if (
Opcode == RISCV::TH_LDD ||
Opcode == RISCV::TH_LWUD ||
3348 Opcode == RISCV::TH_LWD) {
3353 if (Rs1 == Rd1 && Rs1 == Rd2) {
3355 return Error(Loc,
"The source register and destination registers "
3356 "cannot be equal.");
3360 if (
Opcode == RISCV::CM_MVSA01) {
3365 return Error(Loc,
"'rs1' and 'rs2' must be different.");
3369 bool IsTHeadMemPair32 = (
Opcode == RISCV::TH_LWD ||
3371 bool IsTHeadMemPair64 = (
Opcode == RISCV::TH_LDD ||
Opcode == RISCV::TH_SDD);
3376 return Error(Loc,
"Operand must be constant 3.");
3379 return Error(Loc,
"Operand must be constant 4.");
3382 bool IsAMOCAS_D =
Opcode == RISCV::AMOCAS_D ||
Opcode == RISCV::AMOCAS_D_AQ ||
3383 Opcode == RISCV::AMOCAS_D_RL ||
3384 Opcode == RISCV::AMOCAS_D_AQ_RL;
3385 bool IsAMOCAS_Q =
Opcode == RISCV::AMOCAS_Q ||
Opcode == RISCV::AMOCAS_Q_AQ ||
3386 Opcode == RISCV::AMOCAS_Q_RL ||
3387 Opcode == RISCV::AMOCAS_Q_AQ_RL;
3388 if ((!isRV64() && IsAMOCAS_D) || IsAMOCAS_Q) {
3391 assert(Rd >= RISCV::X0 && Rd <= RISCV::X31);
3392 if ((Rd - RISCV::X0) % 2 != 0) {
3394 return Error(Loc,
"The destination register must be even.");
3396 assert(Rs2 >= RISCV::X0 && Rs2 <= RISCV::X31);
3397 if ((Rs2 - RISCV::X0) % 2 != 0) {
3399 return Error(Loc,
"The source register must be even.");
3407 if (
Opcode == RISCV::VC_V_XVW ||
Opcode == RISCV::VC_V_IVW ||
3408 Opcode == RISCV::VC_V_FVW ||
Opcode == RISCV::VC_V_VVW) {
3414 if (VCIXDst == VCIXRs1)
3415 return Error(VCIXDstLoc,
"The destination vector register group cannot"
3416 " overlap the source vector register group.");
3420 if (VCIXDst == VCIXRs2)
3421 return Error(VCIXDstLoc,
"The destination vector register group cannot"
3422 " overlap the source vector register group.");
3437 if (DestReg == CheckReg)
3438 return Error(Loc,
"The destination vector register group cannot overlap"
3439 " the source vector register group.");
3443 if (DestReg == CheckReg)
3444 return Error(Loc,
"The destination vector register group cannot overlap"
3445 " the source vector register group.");
3450 if (
Opcode == RISCV::VADC_VVM ||
Opcode == RISCV::VADC_VXM ||
3451 Opcode == RISCV::VADC_VIM ||
Opcode == RISCV::VSBC_VVM ||
3452 Opcode == RISCV::VSBC_VXM ||
Opcode == RISCV::VFMERGE_VFM ||
3453 Opcode == RISCV::VMERGE_VIM ||
Opcode == RISCV::VMERGE_VVM ||
3454 Opcode == RISCV::VMERGE_VXM)
3455 return Error(Loc,
"The destination vector register group cannot be V0.");
3462 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
3463 "Unexpected register for mask operand");
3465 if (DestReg == CheckReg)
3466 return Error(Loc,
"The destination vector register group cannot overlap"
3467 " the mask register.");
3472bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
3480 case RISCV::PseudoLLAImm:
3481 case RISCV::PseudoLAImm:
3482 case RISCV::PseudoLI: {
3499 Imm = SignExtend64<32>(Imm);
3500 emitLoadImm(
Reg, Imm, Out);
3503 case RISCV::PseudoLLA:
3504 emitLoadLocalAddress(Inst, IDLoc, Out);
3506 case RISCV::PseudoLGA:
3507 emitLoadGlobalAddress(Inst, IDLoc, Out);
3509 case RISCV::PseudoLA:
3510 emitLoadAddress(Inst, IDLoc, Out);
3512 case RISCV::PseudoLA_TLS_IE:
3513 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3515 case RISCV::PseudoLA_TLS_GD:
3516 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3518 case RISCV::PseudoLB:
3519 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
3521 case RISCV::PseudoLBU:
3522 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
3524 case RISCV::PseudoLH:
3525 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
3527 case RISCV::PseudoLHU:
3528 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
3530 case RISCV::PseudoLW:
3531 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
3533 case RISCV::PseudoLWU:
3534 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
3536 case RISCV::PseudoLD:
3537 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
3539 case RISCV::PseudoFLH:
3540 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
3542 case RISCV::PseudoFLW:
3543 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
3545 case RISCV::PseudoFLD:
3546 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
3548 case RISCV::PseudoSB:
3549 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
3551 case RISCV::PseudoSH:
3552 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
3554 case RISCV::PseudoSW:
3555 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
3557 case RISCV::PseudoSD:
3558 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
3560 case RISCV::PseudoFSH:
3561 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
3563 case RISCV::PseudoFSW:
3564 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
3566 case RISCV::PseudoFSD:
3567 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
3569 case RISCV::PseudoAddTPRel:
3570 if (checkPseudoAddTPRel(Inst,
Operands))
3573 case RISCV::PseudoSEXT_B:
3574 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
3576 case RISCV::PseudoSEXT_H:
3577 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
3579 case RISCV::PseudoZEXT_H:
3580 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
3582 case RISCV::PseudoZEXT_W:
3583 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
3585 case RISCV::PseudoVMSGEU_VX:
3586 case RISCV::PseudoVMSGEU_VX_M:
3587 case RISCV::PseudoVMSGEU_VX_M_T:
3588 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3590 case RISCV::PseudoVMSGE_VX:
3591 case RISCV::PseudoVMSGE_VX_M:
3592 case RISCV::PseudoVMSGE_VX_M_T:
3593 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3595 case RISCV::PseudoVMSGE_VI:
3596 case RISCV::PseudoVMSLT_VI: {
3600 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3609 case RISCV::PseudoVMSGEU_VI:
3610 case RISCV::PseudoVMSLTU_VI: {
3617 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3627 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3641 emitToStreamer(Out, Inst);
static const char * getSubtargetFeatureName(uint64_t Val)
static unsigned MatchRegisterName(StringRef Name)
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static unsigned 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
#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)
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 matchRegisterNameHelper(bool IsRVE, StringRef Name)
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)
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)
static constexpr uint32_t Opcode
Class for arbitrary precision integers.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
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 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 MCAsmLayout *Layout, 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)...
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
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.
ArrayRef< MCOperandInfo > operands() const
unsigned short NumOperands
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 createReg(unsigned Reg)
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createImm(int64_t Val)
unsigned 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.
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.
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
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...
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual unsigned checkTargetMatchPredicate(MCInst &Inst)
checkTargetMatchPredicate - Validate the instruction match against any complex target predicates not ...
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
Target specific streamer interface.
This represents an "assembler immediate".
uint32_t getRefKind() const
const MCSymbolRefExpr * getSymB() const
const MCSymbolRefExpr * getSymA() const
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 bool isSupportedExtension(StringRef Ext)
static llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true, bool IgnoreUnknown=false)
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)
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.
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.
const CustomOperand< const MCSubtargetInfo & > Msg[]
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.
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
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, bool IsEABI)
void printSpimm(int64_t Spimm, raw_ostream &OS)
@ 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.
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.