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;
113 SMLoc &EndLoc)
override;
120 bool parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
unsigned &Sew,
121 unsigned &Lmul,
bool &Fractional,
bool &TailAgnostic,
123 bool generateVTypeError(
SMLoc ErrorLoc);
157 void emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
161 void emitPseudoExtend(
MCInst &Inst,
bool SignExtend, int64_t Width,
190#define GET_ASSEMBLER_HEADER
191#include "RISCVGenAsmMatcher.inc"
217 bool ExpectNegative =
false);
219 return parseZcmpStackAdj(
Operands,
true);
224 bool parseDirectiveOption();
225 bool parseDirectiveAttribute();
226 bool parseDirectiveInsn(
SMLoc L);
227 bool parseDirectiveVariantCC();
233 bool FromOptionDirective);
236 if (!(
getSTI().hasFeature(Feature))) {
244 if (
getSTI().hasFeature(Feature)) {
251 void pushFeatureBits() {
253 "These two stacks must be kept synchronized");
255 ParserOptionsStack.
push_back(ParserOptions);
258 bool popFeatureBits() {
260 "These two stacks must be kept synchronized");
261 if (FeatureBitStack.
empty())
273 std::unique_ptr<RISCVOperand> defaultMaskRegOp()
const;
274 std::unique_ptr<RISCVOperand> defaultFRMArgOp()
const;
275 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp()
const;
278 enum RISCVMatchResultTy {
280 Match_RequiresEvenGPRs,
281#define GET_OPERAND_DIAGNOSTIC_TYPES
282#include "RISCVGenAsmMatcher.inc"
283#undef GET_OPERAND_DIAGNOSTIC_TYPES
286 static bool classifySymbolRef(
const MCExpr *Expr,
288 static bool isSymbolDiff(
const MCExpr *Expr);
302 if (ABIName.ends_with(
"f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
303 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
304 "doesn't support the F instruction set extension (ignoring "
306 }
else if (ABIName.ends_with(
"d") &&
307 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
308 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
309 "doesn't support the D instruction set extension (ignoring "
322 getTargetStreamer().emitTargetAttributes(STI,
false);
391 SMLoc StartLoc, EndLoc;
397 struct SysRegOp SysReg;
398 struct VTypeOp VType;
400 struct FenceOp Fence;
401 struct RlistOp Rlist;
402 struct SpimmOp Spimm;
406 RISCVOperand(KindTy K) :
Kind(
K) {}
411 StartLoc =
o.StartLoc;
414 case KindTy::Register:
417 case KindTy::Immediate:
420 case KindTy::FPImmediate:
426 case KindTy::SystemRegister:
450 bool isToken()
const override {
return Kind == KindTy::Token; }
451 bool isReg()
const override {
return Kind == KindTy::Register; }
452 bool isV0Reg()
const {
453 return Kind == KindTy::Register &&
Reg.RegNum == RISCV::V0;
455 bool isAnyReg()
const {
456 return Kind == KindTy::Register &&
457 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum) ||
458 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg.RegNum) ||
459 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg.RegNum));
461 bool isAnyRegC()
const {
462 return Kind == KindTy::Register &&
463 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
465 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
468 bool isImm()
const override {
return Kind == KindTy::Immediate; }
469 bool isMem()
const override {
return false; }
470 bool isSystemRegister()
const {
return Kind == KindTy::SystemRegister; }
471 bool isRegReg()
const {
return Kind == KindTy::RegReg; }
472 bool isRlist()
const {
return Kind == KindTy::Rlist; }
473 bool isSpimm()
const {
return Kind == KindTy::Spimm; }
476 return Kind == KindTy::Register &&
477 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum);
480 bool isGPRAsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
482 bool isGPRPair()
const {
483 return Kind == KindTy::Register &&
484 RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
488 static bool evaluateConstantImm(
const MCExpr *Expr, int64_t &Imm,
490 if (
auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
492 return RE->evaluateAsConstant(Imm);
495 if (
auto CE = dyn_cast<MCConstantExpr>(Expr)) {
497 Imm =
CE->getValue();
506 template <
int N>
bool isBareSimmNLsb0()
const {
511 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
514 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
522 bool isBareSymbol()
const {
526 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
528 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
532 bool isCallSymbol()
const {
536 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
538 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
543 bool isPseudoJumpSymbol()
const {
547 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
549 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
553 bool isTPRelAddSymbol()
const {
557 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
559 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
563 bool isTLSDESCCallSymbol()
const {
567 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
569 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
573 bool isCSRSystemRegister()
const {
return isSystemRegister(); }
575 bool isVTypeImm(
unsigned N)
const {
580 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
586 bool isVTypeI10()
const {
587 if (Kind == KindTy::Immediate)
588 return isVTypeImm(10);
589 return Kind == KindTy::VType;
591 bool isVTypeI11()
const {
592 if (Kind == KindTy::Immediate)
593 return isVTypeImm(11);
594 return Kind == KindTy::VType;
599 bool isFenceArg()
const {
return Kind == KindTy::Fence; }
602 bool isFRMArg()
const {
return Kind == KindTy::FRM; }
603 bool isFRMArgLegacy()
const {
return Kind == KindTy::FRM; }
607 bool isLoadFPImm()
const {
610 if (Kind != KindTy::FPImmediate)
613 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
616 return Idx >= 0 &&
Idx != 1;
619 bool isImmXLenLI()
const {
624 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
634 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
637 return RISCVAsmParser::isSymbolDiff(getImm());
640 bool isImmXLenLI_Restricted()
const {
645 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
648 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
651 bool isUImmLog2XLen()
const {
656 if (!evaluateConstantImm(getImm(), Imm, VK) ||
659 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
662 bool isUImmLog2XLenNonZero()
const {
667 if (!evaluateConstantImm(getImm(), Imm, VK) ||
672 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
675 bool isUImmLog2XLenHalf()
const {
680 if (!evaluateConstantImm(getImm(), Imm, VK) ||
683 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
686 template <
unsigned N>
bool IsUImm()
const {
691 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
695 bool isUImm1()
const {
return IsUImm<1>(); }
696 bool isUImm2()
const {
return IsUImm<2>(); }
697 bool isUImm3()
const {
return IsUImm<3>(); }
698 bool isUImm4()
const {
return IsUImm<4>(); }
699 bool isUImm5()
const {
return IsUImm<5>(); }
700 bool isUImm6()
const {
return IsUImm<6>(); }
701 bool isUImm7()
const {
return IsUImm<7>(); }
702 bool isUImm8()
const {
return IsUImm<8>(); }
703 bool isUImm20()
const {
return IsUImm<20>(); }
705 bool isUImm8GE32()
const {
710 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
711 return IsConstantImm && isUInt<8>(Imm) &&
Imm >= 32 &&
715 bool isRnumArg()
const {
720 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
721 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(10) &&
725 bool isRnumArg_0_7()
const {
730 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
731 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(7) &&
735 bool isRnumArg_1_10()
const {
740 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
741 return IsConstantImm &&
Imm >= INT64_C(1) &&
Imm <= INT64_C(10) &&
745 bool isRnumArg_2_14()
const {
750 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
751 return IsConstantImm &&
Imm >= INT64_C(2) &&
Imm <= INT64_C(14) &&
755 bool isSImm5()
const {
760 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
761 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
765 bool isSImm6()
const {
770 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
771 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
775 bool isSImm6NonZero()
const {
780 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
781 return IsConstantImm &&
Imm != 0 &&
782 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
786 bool isCLUIImm()
const {
791 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
792 return IsConstantImm && (
Imm != 0) &&
793 (isUInt<5>(Imm) || (
Imm >= 0xfffe0 &&
Imm <= 0xfffff)) &&
797 bool isUImm2Lsb0()
const {
802 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
803 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
807 bool isUImm7Lsb00()
const {
812 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
813 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
817 bool isUImm8Lsb00()
const {
822 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
823 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
827 bool isUImm8Lsb000()
const {
832 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
833 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
837 bool isSImm9Lsb0()
const {
return isBareSimmNLsb0<9>(); }
839 bool isUImm9Lsb000()
const {
844 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
845 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
849 bool isUImm10Lsb00NonZero()
const {
854 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
855 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (
Imm != 0) &&
861 static int64_t fixImmediateForRV32(int64_t Imm,
bool IsRV64Imm) {
862 if (IsRV64Imm || !isUInt<32>(Imm))
864 return SignExtend64<32>(Imm);
867 bool isSImm12()
const {
873 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
875 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
877 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
886 bool isSImm12Lsb0()
const {
return isBareSimmNLsb0<12>(); }
888 bool isSImm12Lsb00000()
const {
893 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
894 return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
898 bool isSImm13Lsb0()
const {
return isBareSimmNLsb0<13>(); }
900 bool isSImm10Lsb0000NonZero()
const {
905 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
906 return IsConstantImm && (
Imm != 0) && isShiftedInt<6, 4>(Imm) &&
910 bool isUImm20LUI()
const {
916 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
917 if (!IsConstantImm) {
918 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
928 bool isUImm20AUIPC()
const {
934 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
935 if (!IsConstantImm) {
936 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
952 bool isSImm21Lsb0JAL()
const {
return isBareSimmNLsb0<21>(); }
954 bool isImmZero()
const {
959 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
963 bool isSImm5Plus1()
const {
968 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
969 return IsConstantImm &&
970 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
975 SMLoc getStartLoc()
const override {
return StartLoc; }
977 SMLoc getEndLoc()
const override {
return EndLoc; }
979 bool isRV64Imm()
const {
980 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
985 assert(Kind == KindTy::Register &&
"Invalid type access!");
990 assert(Kind == KindTy::SystemRegister &&
"Invalid type access!");
991 return StringRef(SysReg.Data, SysReg.Length);
994 const MCExpr *getImm()
const {
995 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
1000 assert(Kind == KindTy::FPImmediate &&
"Invalid type access!");
1005 assert(Kind == KindTy::Token &&
"Invalid type access!");
1009 unsigned getVType()
const {
1010 assert(Kind == KindTy::VType &&
"Invalid type access!");
1015 assert(Kind == KindTy::FRM &&
"Invalid type access!");
1019 unsigned getFence()
const {
1020 assert(Kind == KindTy::Fence &&
"Invalid type access!");
1033 case KindTy::Immediate:
1036 case KindTy::FPImmediate:
1038 case KindTy::Register:
1042 OS <<
"'" << getToken() <<
"'";
1044 case KindTy::SystemRegister:
1045 OS <<
"<sysreg: " << getSysReg() <<
'>';
1054 roundingModeToString(getFRM());
1072 case KindTy::RegReg:
1079 static std::unique_ptr<RISCVOperand> createToken(
StringRef Str,
SMLoc S) {
1080 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1087 static std::unique_ptr<RISCVOperand>
1088 createReg(
unsigned RegNo,
SMLoc S,
SMLoc E,
bool IsGPRAsFPR =
false) {
1089 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1090 Op->Reg.RegNum = RegNo;
1091 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1097 static std::unique_ptr<RISCVOperand> createImm(
const MCExpr *Val,
SMLoc S,
1099 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1101 Op->Imm.IsRV64 = IsRV64;
1107 static std::unique_ptr<RISCVOperand> createFPImm(
uint64_t Val,
SMLoc S) {
1108 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1109 Op->FPImm.Val = Val;
1115 static std::unique_ptr<RISCVOperand> createSysReg(
StringRef Str,
SMLoc S,
1116 unsigned Encoding) {
1117 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1118 Op->SysReg.Data = Str.data();
1119 Op->SysReg.Length = Str.size();
1126 static std::unique_ptr<RISCVOperand>
1128 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1135 static std::unique_ptr<RISCVOperand> createFenceArg(
unsigned Val,
SMLoc S) {
1136 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1137 Op->Fence.Val = Val;
1143 static std::unique_ptr<RISCVOperand> createVType(
unsigned VTypeI,
SMLoc S) {
1144 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1145 Op->VType.Val = VTypeI;
1151 static std::unique_ptr<RISCVOperand> createRlist(
unsigned RlistEncode,
1153 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1154 Op->Rlist.Val = RlistEncode;
1159 static std::unique_ptr<RISCVOperand> createRegReg(
unsigned Reg1No,
1160 unsigned Reg2No,
SMLoc S) {
1161 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1162 Op->RegReg.Reg1 = Reg1No;
1163 Op->RegReg.Reg2 = Reg2No;
1169 static std::unique_ptr<RISCVOperand> createSpimm(
unsigned Spimm,
SMLoc S) {
1170 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1171 Op->Spimm.Val = Spimm;
1176 static void addExpr(
MCInst &Inst,
const MCExpr *Expr,
bool IsRV64Imm) {
1177 assert(Expr &&
"Expr shouldn't be null!");
1180 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1190 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
1191 assert(
N == 1 &&
"Invalid number of operands!");
1195 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
1196 assert(
N == 1 &&
"Invalid number of operands!");
1197 addExpr(Inst, getImm(), isRV64Imm());
1200 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
1201 assert(
N == 1 &&
"Invalid number of operands!");
1203 addExpr(Inst, getImm(), isRV64Imm());
1208 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
1212 void addFenceArgOperands(
MCInst &Inst,
unsigned N)
const {
1213 assert(
N == 1 &&
"Invalid number of operands!");
1217 void addCSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
1218 assert(
N == 1 &&
"Invalid number of operands!");
1225 void addVTypeIOperands(
MCInst &Inst,
unsigned N)
const {
1226 assert(
N == 1 &&
"Invalid number of operands!");
1228 if (Kind == KindTy::Immediate) {
1230 [[maybe_unused]]
bool IsConstantImm =
1231 evaluateConstantImm(getImm(), Imm, VK);
1232 assert(IsConstantImm &&
"Invalid VTypeI Operand!");
1239 void addRlistOperands(
MCInst &Inst,
unsigned N)
const {
1240 assert(
N == 1 &&
"Invalid number of operands!");
1244 void addRegRegOperands(
MCInst &Inst,
unsigned N)
const {
1245 assert(
N == 1 &&
"Invalid number of operands!");
1250 void addSpimmOperands(
MCInst &Inst,
unsigned N)
const {
1251 assert(
N == 1 &&
"Invalid number of operands!");
1255 void addFRMArgOperands(
MCInst &Inst,
unsigned N)
const {
1256 assert(
N == 1 &&
"Invalid number of operands!");
1262#define GET_REGISTER_MATCHER
1263#define GET_SUBTARGET_FEATURE_NAME
1264#define GET_MATCHER_IMPLEMENTATION
1265#define GET_MNEMONIC_SPELL_CHECKER
1266#include "RISCVGenAsmMatcher.inc"
1269 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1270 return Reg - RISCV::F0_D + RISCV::F0_H;
1274 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1275 return Reg - RISCV::F0_D + RISCV::F0_F;
1280 unsigned RegClassID;
1281 if (Kind == MCK_VRM2)
1282 RegClassID = RISCV::VRM2RegClassID;
1283 else if (Kind == MCK_VRM4)
1284 RegClassID = RISCV::VRM4RegClassID;
1285 else if (Kind == MCK_VRM8)
1286 RegClassID = RISCV::VRM8RegClassID;
1290 &RISCVMCRegisterClasses[RegClassID]);
1295 RISCVOperand &
Op =
static_cast<RISCVOperand &
>(AsmOp);
1297 return Match_InvalidOperand;
1301 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg);
1303 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
Reg);
1304 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg);
1308 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1309 (IsRegFPR64C &&
Kind == MCK_FPR32C)) {
1311 return Match_Success;
1315 if (IsRegFPR64 && Kind == MCK_FPR16) {
1317 return Match_Success;
1321 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1323 if (
Op.Reg.RegNum == 0)
1324 return Match_InvalidOperand;
1325 return Match_Success;
1327 return Match_InvalidOperand;
1330unsigned RISCVAsmParser::checkTargetMatchPredicate(
MCInst &Inst) {
1334 if (MCID.
operands()[
I].RegClass == RISCV::GPRPairRegClassID) {
1339 if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].
contains(
Reg))
1343 if (((
Reg.id() - RISCV::X0) & 1) != 0)
1344 return Match_RequiresEvenGPRs;
1348 return Match_Success;
1351bool RISCVAsmParser::generateImmOutOfRangeError(
1353 const Twine &Msg =
"immediate must be an integer in the range") {
1357bool RISCVAsmParser::generateImmOutOfRangeError(
1359 const Twine &Msg =
"immediate must be an integer in the range") {
1361 return generateImmOutOfRangeError(ErrorLoc,
Lower,
Upper, Msg);
1364bool RISCVAsmParser::MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1368 bool MatchingInlineAsm) {
1378 if (validateInstruction(Inst,
Operands))
1380 return processInstruction(Inst, IDLoc,
Operands, Out);
1381 case Match_MissingFeature: {
1382 assert(MissingFeatures.
any() &&
"Unknown missing features!");
1383 bool FirstFeature =
true;
1384 std::string
Msg =
"instruction requires the following:";
1385 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
1386 if (MissingFeatures[i]) {
1387 Msg += FirstFeature ?
" " :
", ";
1389 FirstFeature =
false;
1392 return Error(IDLoc, Msg);
1394 case Match_MnemonicFail: {
1395 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1396 std::string Suggestion = RISCVMnemonicSpellCheck(
1397 ((RISCVOperand &)*
Operands[0]).getToken(), FBS, 0);
1398 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
1400 case Match_InvalidOperand: {
1401 SMLoc ErrorLoc = IDLoc;
1404 return Error(ErrorLoc,
"too few operands for instruction");
1407 if (ErrorLoc ==
SMLoc())
1410 return Error(ErrorLoc,
"invalid operand for instruction");
1417 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1418 SMLoc ErrorLoc = IDLoc;
1420 return Error(ErrorLoc,
"too few operands for instruction");
1426 case Match_RequiresEvenGPRs:
1428 "double precision floating point operands must use even "
1429 "numbered X register");
1430 case Match_InvalidImmXLenLI:
1433 return Error(ErrorLoc,
"operand must be a constant 64-bit integer");
1436 std::numeric_limits<int32_t>::min(),
1437 std::numeric_limits<uint32_t>::max());
1438 case Match_InvalidImmXLenLI_Restricted:
1441 return Error(ErrorLoc,
"operand either must be a constant 64-bit integer "
1442 "or a bare symbol name");
1444 return generateImmOutOfRangeError(
1446 std::numeric_limits<uint32_t>::max(),
1447 "operand either must be a bare symbol name or an immediate integer in "
1449 case Match_InvalidImmZero: {
1451 return Error(ErrorLoc,
"immediate must be zero");
1453 case Match_InvalidUImmLog2XLen:
1457 case Match_InvalidUImmLog2XLenNonZero:
1461 case Match_InvalidUImmLog2XLenHalf:
1465 case Match_InvalidUImm1:
1467 case Match_InvalidUImm2:
1469 case Match_InvalidUImm2Lsb0:
1471 "immediate must be one of");
1472 case Match_InvalidUImm3:
1474 case Match_InvalidUImm4:
1476 case Match_InvalidUImm5:
1478 case Match_InvalidUImm6:
1480 case Match_InvalidUImm7:
1482 case Match_InvalidUImm8:
1484 case Match_InvalidUImm8GE32:
1486 case Match_InvalidSImm5:
1489 case Match_InvalidSImm6:
1492 case Match_InvalidSImm6NonZero:
1493 return generateImmOutOfRangeError(
1495 "immediate must be non-zero in the range");
1496 case Match_InvalidCLUIImm:
1497 return generateImmOutOfRangeError(
1499 "immediate must be in [0xfffe0, 0xfffff] or");
1500 case Match_InvalidUImm7Lsb00:
1501 return generateImmOutOfRangeError(
1503 "immediate must be a multiple of 4 bytes in the range");
1504 case Match_InvalidUImm8Lsb00:
1505 return generateImmOutOfRangeError(
1507 "immediate must be a multiple of 4 bytes in the range");
1508 case Match_InvalidUImm8Lsb000:
1509 return generateImmOutOfRangeError(
1511 "immediate must be a multiple of 8 bytes in the range");
1512 case Match_InvalidSImm9Lsb0:
1513 return generateImmOutOfRangeError(
1515 "immediate must be a multiple of 2 bytes in the range");
1516 case Match_InvalidUImm9Lsb000:
1517 return generateImmOutOfRangeError(
1519 "immediate must be a multiple of 8 bytes in the range");
1520 case Match_InvalidUImm10Lsb00NonZero:
1521 return generateImmOutOfRangeError(
1523 "immediate must be a multiple of 4 bytes in the range");
1524 case Match_InvalidSImm10Lsb0000NonZero:
1525 return generateImmOutOfRangeError(
1527 "immediate must be a multiple of 16 bytes and non-zero in the range");
1528 case Match_InvalidSImm12:
1529 return generateImmOutOfRangeError(
1531 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1532 "integer in the range");
1533 case Match_InvalidSImm12Lsb0:
1534 return generateImmOutOfRangeError(
1536 "immediate must be a multiple of 2 bytes in the range");
1537 case Match_InvalidSImm12Lsb00000:
1538 return generateImmOutOfRangeError(
1540 "immediate must be a multiple of 32 bytes in the range");
1541 case Match_InvalidSImm13Lsb0:
1542 return generateImmOutOfRangeError(
1544 "immediate must be a multiple of 2 bytes in the range");
1545 case Match_InvalidUImm20LUI:
1547 "operand must be a symbol with "
1548 "%hi/%tprel_hi modifier or an integer in "
1550 case Match_InvalidUImm20:
1552 case Match_InvalidUImm20AUIPC:
1553 return generateImmOutOfRangeError(
1555 "operand must be a symbol with a "
1556 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1557 "an integer in the range");
1558 case Match_InvalidSImm21Lsb0JAL:
1559 return generateImmOutOfRangeError(
1561 "immediate must be a multiple of 2 bytes in the range");
1562 case Match_InvalidCSRSystemRegister: {
1564 "operand must be a valid system register "
1565 "name or an integer in the range");
1567 case Match_InvalidLoadFPImm: {
1569 return Error(ErrorLoc,
"operand must be a valid floating-point constant");
1571 case Match_InvalidBareSymbol: {
1573 return Error(ErrorLoc,
"operand must be a bare symbol name");
1575 case Match_InvalidPseudoJumpSymbol: {
1577 return Error(ErrorLoc,
"operand must be a valid jump target");
1579 case Match_InvalidCallSymbol: {
1581 return Error(ErrorLoc,
"operand must be a bare symbol name");
1583 case Match_InvalidTPRelAddSymbol: {
1585 return Error(ErrorLoc,
"operand must be a symbol with %tprel_add modifier");
1587 case Match_InvalidTLSDESCCallSymbol: {
1589 return Error(ErrorLoc,
1590 "operand must be a symbol with %tlsdesc_call modifier");
1592 case Match_InvalidRTZArg: {
1594 return Error(ErrorLoc,
"operand must be 'rtz' floating-point rounding mode");
1596 case Match_InvalidVTypeI: {
1598 return generateVTypeError(ErrorLoc);
1600 case Match_InvalidVMaskRegister: {
1602 return Error(ErrorLoc,
"operand must be v0.t");
1604 case Match_InvalidSImm5Plus1: {
1607 "immediate must be in the range");
1609 case Match_InvalidRlist: {
1613 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1615 case Match_InvalidStackAdj: {
1619 "stack adjustment is invalid for this instruction and register list; "
1620 "refer to Zc spec for a detailed range of stack adjustment");
1622 case Match_InvalidRnumArg: {
1625 case Match_InvalidRegReg: {
1627 return Error(ErrorLoc,
"operands must be register and register");
1645 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1646 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1649 if (isRVE() &&
Reg >= RISCV::X16 &&
Reg <= RISCV::X31)
1650 Reg = RISCV::NoRegister;
1656 if (!tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess())
1657 return Error(StartLoc,
"invalid register name");
1663 const AsmToken &Tok = getParser().getTok();
1678 SMLoc FirstS = getLoc();
1679 bool HadParens =
false;
1686 size_t ReadCount = getLexer().peekTokens(Buf);
1689 LParen = getParser().getTok();
1694 switch (getLexer().getKind()) {
1697 getLexer().UnLex(LParen);
1705 getLexer().UnLex(LParen);
1709 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1713 Operands.push_back(RISCVOperand::createReg(RegNo, S,
E));
1718 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1729 switch (getLexer().getKind()) {
1739 if (getParser().parseExpression(Res,
E))
1742 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1744 int64_t
Imm =
CE->getValue();
1745 if (isUInt<7>(Imm)) {
1746 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1755 if (getParser().parseIdentifier(Identifier))
1758 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1760 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1761 "Unexpected opcode");
1764 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1774 return generateImmOutOfRangeError(
1776 "opcode must be a valid opcode name or an immediate in the range");
1784 switch (getLexer().getKind()) {
1794 if (getParser().parseExpression(Res,
E))
1797 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1799 int64_t
Imm =
CE->getValue();
1800 if (Imm >= 0 && Imm <= 2) {
1801 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1810 if (getParser().parseIdentifier(Identifier))
1814 if (Identifier ==
"C0")
1816 else if (Identifier ==
"C1")
1818 else if (Identifier ==
"C2")
1825 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1834 return generateImmOutOfRangeError(
1836 "opcode must be a valid opcode name or an immediate in the range");
1843 switch (getLexer().getKind()) {
1853 if (getParser().parseExpression(Res))
1856 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1858 int64_t
Imm =
CE->getValue();
1859 if (isUInt<12>(Imm)) {
1860 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1864 RISCVOperand::createSysReg(SysReg ? SysReg->Name :
"", S, Imm));
1869 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1873 if (getParser().parseIdentifier(Identifier))
1876 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1878 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1880 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1881 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
1882 SysReg->Name +
"'");
1886 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))
1887 return Error(S,
"system register use requires an option to be enabled");
1889 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1893 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
1894 "operand must be a valid system register "
1895 "name or an integer in the range");
1899 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1912 if (
Identifier.compare_insensitive(
"inf") == 0) {
1915 getTok().getEndLoc(), isRV64()));
1916 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
1919 getTok().getEndLoc(), isRV64()));
1920 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
1923 getTok().getEndLoc(), isRV64()));
1925 return TokError(
"invalid floating point literal");
1938 return TokError(
"invalid floating point immediate");
1941 APFloat RealVal(APFloat::IEEEdouble());
1943 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
1945 return TokError(
"invalid floating point representation");
1948 RealVal.changeSign();
1950 Operands.push_back(RISCVOperand::createFPImm(
1951 RealVal.bitcastToAPInt().getZExtValue(), S));
1963 switch (getLexer().getKind()) {
1975 if (getParser().parseExpression(Res,
E))
1979 return parseOperandWithModifier(
Operands);
1982 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1994 return Error(getLoc(),
"expected valid identifier for operand modifier");
1998 return Error(getLoc(),
"unrecognized operand modifier");
2005 if (getParser().parseParenExpression(SubExpr,
E))
2009 Operands.push_back(RISCVOperand::createImm(ModExpr, S,
E, isRV64()));
2021 AsmToken Tok = getLexer().getTok();
2023 if (getParser().parseIdentifier(Identifier))
2029 return Error(getLoc(),
"'@plt' operand not valid for instruction");
2031 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2033 if (
Sym->isVariable()) {
2034 const MCExpr *
V =
Sym->getVariableValue(
false);
2035 if (!isa<MCSymbolRefExpr>(V)) {
2036 getLexer().UnLex(Tok);
2044 switch (getLexer().getKind()) {
2046 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2059 if (getParser().parseExpression(Expr,
E))
2062 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2078 if (getParser().parseIdentifier(Identifier))
2086 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2089 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2098 if (getParser().parseExpression(Res,
E))
2101 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef ||
2102 cast<MCSymbolRefExpr>(Res)->getKind() ==
2103 MCSymbolRefExpr::VariantKind::VK_PLT)
2104 return Error(S,
"operand must be a valid jump target");
2107 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
2128bool RISCVAsmParser::parseVTypeToken(
const AsmToken &Tok, VTypeState &State,
2129 unsigned &Sew,
unsigned &Lmul,
2130 bool &Fractional,
bool &TailAgnostic,
2131 bool &MaskAgnostic) {
2138 case VTypeState_SEW:
2145 State = VTypeState_LMUL;
2147 case VTypeState_LMUL: {
2155 State = VTypeState_TailPolicy;
2158 case VTypeState_TailPolicy:
2159 if (Identifier ==
"ta")
2160 TailAgnostic =
true;
2161 else if (Identifier ==
"tu")
2162 TailAgnostic =
false;
2165 State = VTypeState_MaskPolicy;
2167 case VTypeState_MaskPolicy:
2168 if (Identifier ==
"ma")
2169 MaskAgnostic =
true;
2170 else if (Identifier ==
"mu")
2171 MaskAgnostic =
false;
2174 State = VTypeState_Done;
2176 case VTypeState_Done:
2189 bool Fractional =
false;
2190 bool TailAgnostic =
false;
2191 bool MaskAgnostic =
false;
2193 VTypeState State = VTypeState_SEW;
2195 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2202 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2214 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2218 return generateVTypeError(S);
2221bool RISCVAsmParser::generateVTypeError(
SMLoc ErrorLoc) {
2225 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2233 if (!
Name.consume_back(
".t"))
2234 return Error(getLoc(),
"expected '.t' suffix");
2239 if (RegNo != RISCV::V0)
2244 Operands.push_back(RISCVOperand::createReg(RegNo, S,
E));
2260 Operands.push_back(RISCVOperand::createReg(
2261 RegNo, S,
E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2265template <
bool IsRV64>
2267 return parseGPRPair(
Operands, IsRV64);
2277 if (!IsRV64Inst && isRV64())
2289 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].
contains(RegNo))
2292 if ((RegNo - RISCV::X0) & 1)
2293 return TokError(
"register must be even");
2301 RegNo, RISCV::sub_gpr_even,
2302 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2303 Operands.push_back(RISCVOperand::createReg(Pair, S,
E));
2310 "operand must be a valid floating point rounding mode mnemonic");
2312 StringRef Str = getLexer().getTok().getIdentifier();
2317 "operand must be a valid floating point rounding mode mnemonic");
2319 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2325 const AsmToken &Tok = getLexer().getTok();
2331 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2345 for (
char c : Str) {
2374 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2380 return TokError(
"operand must be formed of letters selected in-order from "
2387 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2389 if (!parseRegister(
Operands).isSuccess())
2390 return Error(getLoc(),
"expected register");
2394 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2418 std::unique_ptr<RISCVOperand> OptionalImmOp;
2425 SMLoc ImmStart = getLoc();
2426 if (getParser().parseIntToken(ImmVal,
2427 "expected '(' or optional integer offset"))
2432 SMLoc ImmEnd = getLoc();
2435 ImmStart, ImmEnd, isRV64());
2439 OptionalImmOp ?
"expected '(' after optional integer offset"
2440 :
"expected '(' or optional integer offset"))
2443 if (!parseRegister(
Operands).isSuccess())
2444 return Error(getLoc(),
"expected register");
2450 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2452 OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2453 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2466 return Error(getLoc(),
"invalid register");
2473 return Error(getLoc(),
"expected register");
2475 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2478 return Error(getLoc(),
"invalid register");
2484 Operands.push_back(RISCVOperand::createRegReg(
Reg, Reg2, getLoc()));
2497 bool IsEABI = isRVE();
2500 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2505 if (RegStart != RISCV::X1)
2506 return Error(getLoc(),
"register list must start from 'ra' or 'x1'");
2512 return Error(getLoc(),
"invalid register");
2516 return Error(getLoc(),
"invalid register");
2517 if (RegStart != RISCV::X8)
2518 return Error(getLoc(),
2519 "continuous register list must start from 's0' or 'x8'");
2525 StringRef EndName = getLexer().getTok().getIdentifier();
2529 return Error(getLoc(),
"invalid register");
2530 if (IsEABI && RegEnd != RISCV::X9)
2531 return Error(getLoc(),
"contiguous register list of EABI can only be "
2532 "'s0-s1' or 'x8-x9' pair");
2539 if (RegEnd != RISCV::X9)
2542 "first contiguous registers pair of register list must be 'x8-x9'");
2546 return Error(getLoc(),
"invalid register");
2547 StringRef EndName = getLexer().getTok().getIdentifier();
2549 return Error(getLoc(),
2550 "second contiguous registers pair of register list "
2551 "must start from 'x18'");
2557 return Error(getLoc(),
"invalid register");
2558 EndName = getLexer().getTok().getIdentifier();
2560 return Error(getLoc(),
"invalid register");
2567 if (RegEnd == RISCV::X26)
2568 return Error(getLoc(),
"invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2569 "x18-x26} is not supported");
2574 if (RegEnd == RISCV::NoRegister)
2579 return Error(S,
"invalid register list");
2580 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2586 bool ExpectNegative) {
2592 unsigned RlistVal =
static_cast<RISCVOperand *
>(
Operands[1].get())->Rlist.Val;
2594 if (Negative != ExpectNegative ||
2597 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2609 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2616 if (parseRegister(
Operands,
true).isSuccess())
2623 return !parseMemOpBaseReg(
Operands).isSuccess();
2628 Error(getLoc(),
"unknown operand");
2641 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2642 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2643 if (Assembler !=
nullptr) {
2651 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2670 if (getParser().parseEOL(
"unexpected token")) {
2671 getParser().eatToEndOfStatement();
2677bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2681 if (
const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2682 Kind = RE->getKind();
2683 Expr = RE->getSubExpr();
2693bool RISCVAsmParser::isSymbolDiff(
const MCExpr *Expr) {
2706 if (IDVal ==
".option")
2707 return parseDirectiveOption();
2708 if (IDVal ==
".attribute")
2709 return parseDirectiveAttribute();
2710 if (IDVal ==
".insn")
2711 return parseDirectiveInsn(DirectiveID.
getLoc());
2712 if (IDVal ==
".variant_cc")
2713 return parseDirectiveVariantCC();
2718bool RISCVAsmParser::resetToArch(
StringRef Arch,
SMLoc Loc, std::string &Result,
2719 bool FromOptionDirective) {
2722 clearFeatureBits(Feature.Value, Feature.Key);
2731 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
2732 << ErrMsg.getMessage();
2735 return Error(Loc, OutputErrMsg.str());
2737 auto &ISAInfo = *ParseResult;
2740 if (ISAInfo->hasExtension(Feature.Key))
2741 setFeatureBits(Feature.Value, Feature.Key);
2743 if (FromOptionDirective) {
2744 if (ISAInfo->getXLen() == 32 && isRV64())
2745 return Error(Loc,
"bad arch string switching from rv64 to rv32");
2746 else if (ISAInfo->getXLen() == 64 && !isRV64())
2747 return Error(Loc,
"bad arch string switching from rv32 to rv64");
2750 if (ISAInfo->getXLen() == 32)
2751 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
2752 else if (ISAInfo->getXLen() == 64)
2753 setFeatureBits(RISCV::Feature64Bit,
"64bit");
2755 return Error(Loc,
"bad arch string " + Arch);
2757 Result = ISAInfo->toString();
2761bool RISCVAsmParser::parseDirectiveOption() {
2772 if (Option ==
"push") {
2776 getTargetStreamer().emitDirectiveOptionPush();
2781 if (Option ==
"pop") {
2786 getTargetStreamer().emitDirectiveOptionPop();
2787 if (popFeatureBits())
2788 return Error(StartLoc,
".option pop with no .option push");
2793 if (Option ==
"arch") {
2801 Type = RISCVOptionArchArgType::Plus;
2803 Type = RISCVOptionArchArgType::Minus;
2804 else if (!
Args.empty())
2806 "unexpected token, expected + or -");
2808 Type = RISCVOptionArchArgType::Full;
2812 "unexpected token, expected identifier");
2818 if (
Type == RISCVOptionArchArgType::Full) {
2820 if (resetToArch(Arch, Loc, Result,
true))
2833 "Extension version number parsing not currently implemented");
2834 return Error(Loc,
"unknown extension feature");
2839 if (
Type == RISCVOptionArchArgType::Plus) {
2842 setFeatureBits(
Ext->Value,
Ext->Key);
2845 copySTI().setFeatureBits(OldFeatureBits);
2846 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
2851 OutputErrMsg << ErrMsg.getMessage();
2854 return Error(Loc, OutputErrMsg.str());
2857 assert(
Type == RISCVOptionArchArgType::Minus);
2862 if (getSTI().hasFeature(Feature.Value) &&
2863 Feature.Implies.test(
Ext->Value))
2865 Twine(
"Can't disable ") +
Ext->Key +
" extension, " +
2866 Feature.Key +
" extension requires " +
Ext->Key +
2867 " extension be enabled");
2870 clearFeatureBits(
Ext->Value,
Ext->Key);
2877 getTargetStreamer().emitDirectiveOptionArch(Args);
2881 if (Option ==
"rvc") {
2885 getTargetStreamer().emitDirectiveOptionRVC();
2886 setFeatureBits(RISCV::FeatureStdExtC,
"c");
2890 if (Option ==
"norvc") {
2894 getTargetStreamer().emitDirectiveOptionNoRVC();
2895 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
2896 clearFeatureBits(RISCV::FeatureStdExtZca,
"zca");
2900 if (Option ==
"pic") {
2904 getTargetStreamer().emitDirectiveOptionPIC();
2905 ParserOptions.IsPicEnabled =
true;
2909 if (Option ==
"nopic") {
2913 getTargetStreamer().emitDirectiveOptionNoPIC();
2914 ParserOptions.IsPicEnabled =
false;
2918 if (Option ==
"relax") {
2922 getTargetStreamer().emitDirectiveOptionRelax();
2923 setFeatureBits(RISCV::FeatureRelax,
"relax");
2927 if (Option ==
"norelax") {
2931 getTargetStreamer().emitDirectiveOptionNoRelax();
2932 clearFeatureBits(RISCV::FeatureRelax,
"relax");
2938 "'rvc', 'norvc', 'arch', 'relax' or "
2947bool RISCVAsmParser::parseDirectiveAttribute() {
2954 std::optional<unsigned>
Ret =
2957 return Error(TagLoc,
"attribute name not recognised: " +
Name);
2968 if (
check(!CE, TagLoc,
"expected numeric constant"))
2971 Tag =
CE->getValue();
2978 int64_t IntegerValue = 0;
2979 bool IsIntegerValue =
true;
2984 IsIntegerValue =
false;
2987 if (IsIntegerValue) {
2994 return Error(ValueExprLoc,
"expected numeric constant");
2995 IntegerValue =
CE->getValue();
3008 getTargetStreamer().emitAttribute(
Tag, IntegerValue);
3010 getTargetStreamer().emitTextAttribute(
Tag, StringValue);
3013 if (resetToArch(StringValue, ValueExprLoc, Result,
false))
3017 getTargetStreamer().emitTextAttribute(
Tag, Result);
3025 .
Cases(
"r",
"r4",
"i",
"b",
"sb",
"u",
"j",
"uj",
"s",
true)
3026 .
Cases(
"cr",
"ci",
"ciw",
"css",
"cl",
"cs",
"ca",
"cb",
"cj", AllowC)
3032bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
3039 return Error(ErrorLoc,
"expected instruction format");
3041 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3042 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3044 return Error(ErrorLoc,
"invalid instruction format");
3046 std::string FormatName = (
".insn_" +
Format).str();
3063bool RISCVAsmParser::parseDirectiveVariantCC() {
3065 if (getParser().parseIdentifier(
Name))
3066 return TokError(
"expected symbol name");
3069 getTargetStreamer().emitDirectiveVariantCC(
3070 *getContext().getOrCreateSymbol(
Name));
3078 ++RISCVNumInstrsCompressed;
3087 for (
MCInst &Inst : Seq) {
3088 emitToStreamer(Out, Inst);
3095 unsigned SecondOpcode,
SMLoc IDLoc,
3109 const MCExpr *RefToLinkTmpLabel =
3116 .addExpr(RefToLinkTmpLabel));
3119void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
3130 RISCV::ADDI, IDLoc, Out);
3133void RISCVAsmParser::emitLoadGlobalAddress(
MCInst &Inst,
SMLoc IDLoc,
3143 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3145 SecondOpcode, IDLoc, Out);
3148void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
3157 if (ParserOptions.IsPicEnabled)
3158 emitLoadGlobalAddress(Inst, IDLoc, Out);
3160 emitLoadLocalAddress(Inst, IDLoc, Out);
3163void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
3173 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3175 SecondOpcode, IDLoc, Out);
3178void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
3189 RISCV::ADDI, IDLoc, Out);
3192void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
3202 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3204 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3208 Opcode, IDLoc, Out);
3211void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
3212 int64_t Width,
SMLoc IDLoc,
3224 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3225 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3227 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
3240void RISCVAsmParser::emitVMSGE(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
3251 .addReg(RISCV::NoRegister)
3264 "The destination register should not be V0.");
3283 "The destination register should be V0.");
3285 "The temporary vector register should not be V0.");
3290 .addReg(RISCV::NoRegister)
3304 "The temporary vector register should not be V0.");
3309 .addReg(RISCV::NoRegister)
3329bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
3331 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
3334 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3335 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
3336 "%tprel_add modifier");
3342bool RISCVAsmParser::checkPseudoTLSDESCCall(
MCInst &Inst,
3344 assert(Inst.
getOpcode() == RISCV::PseudoTLSDESCCall &&
"Invalid instruction");
3347 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
3348 return Error(ErrorLoc,
"the output operand must be t0/x5 when using "
3349 "%tlsdesc_call modifier");
3355std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
3356 return RISCVOperand::createReg(RISCV::NoRegister,
llvm::SMLoc(),
3360std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
3361 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3365std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp()
const {
3366 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3370bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
3374 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3375 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3378 if (DestReg == TempReg) {
3380 return Error(Loc,
"The temporary vector register cannot be the same as "
3381 "the destination register.");
3385 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3386 Opcode == RISCV::TH_LWD) {
3391 if (Rs1 == Rd1 && Rs1 == Rd2) {
3393 return Error(Loc,
"The source register and destination registers "
3394 "cannot be equal.");
3398 if (Opcode == RISCV::CM_MVSA01) {
3403 return Error(Loc,
"'rs1' and 'rs2' must be different.");
3407 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3408 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3409 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3414 return Error(Loc,
"Operand must be constant 3.");
3417 return Error(Loc,
"Operand must be constant 4.");
3424 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3425 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3431 if (VCIXDst == VCIXRs1)
3432 return Error(VCIXDstLoc,
"The destination vector register group cannot"
3433 " overlap the source vector register group.");
3437 if (VCIXDst == VCIXRs2)
3438 return Error(VCIXDstLoc,
"The destination vector register group cannot"
3439 " overlap the source vector register group.");
3454 if (DestReg == CheckReg)
3455 return Error(Loc,
"The destination vector register group cannot overlap"
3456 " the source vector register group.");
3460 if (DestReg == CheckReg)
3461 return Error(Loc,
"The destination vector register group cannot overlap"
3462 " the source vector register group.");
3467 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3468 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3469 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3470 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3471 Opcode == RISCV::VMERGE_VXM)
3472 return Error(Loc,
"The destination vector register group cannot be V0.");
3479 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
3480 "Unexpected register for mask operand");
3482 if (DestReg == CheckReg)
3483 return Error(Loc,
"The destination vector register group cannot overlap"
3484 " the mask register.");
3489bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
3497 case RISCV::PseudoLLAImm:
3498 case RISCV::PseudoLAImm:
3499 case RISCV::PseudoLI: {
3516 Imm = SignExtend64<32>(Imm);
3517 emitLoadImm(
Reg, Imm, Out);
3520 case RISCV::PseudoLLA:
3521 emitLoadLocalAddress(Inst, IDLoc, Out);
3523 case RISCV::PseudoLGA:
3524 emitLoadGlobalAddress(Inst, IDLoc, Out);
3526 case RISCV::PseudoLA:
3527 emitLoadAddress(Inst, IDLoc, Out);
3529 case RISCV::PseudoLA_TLS_IE:
3530 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3532 case RISCV::PseudoLA_TLS_GD:
3533 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3535 case RISCV::PseudoLB:
3536 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
3538 case RISCV::PseudoLBU:
3539 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
3541 case RISCV::PseudoLH:
3542 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
3544 case RISCV::PseudoLHU:
3545 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
3547 case RISCV::PseudoLW:
3548 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
3550 case RISCV::PseudoLWU:
3551 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
3553 case RISCV::PseudoLD:
3554 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
3556 case RISCV::PseudoFLH:
3557 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
3559 case RISCV::PseudoFLW:
3560 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
3562 case RISCV::PseudoFLD:
3563 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
3565 case RISCV::PseudoSB:
3566 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
3568 case RISCV::PseudoSH:
3569 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
3571 case RISCV::PseudoSW:
3572 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
3574 case RISCV::PseudoSD:
3575 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
3577 case RISCV::PseudoFSH:
3578 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
3580 case RISCV::PseudoFSW:
3581 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
3583 case RISCV::PseudoFSD:
3584 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
3586 case RISCV::PseudoAddTPRel:
3587 if (checkPseudoAddTPRel(Inst,
Operands))
3590 case RISCV::PseudoTLSDESCCall:
3591 if (checkPseudoTLSDESCCall(Inst,
Operands))
3594 case RISCV::PseudoSEXT_B:
3595 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
3597 case RISCV::PseudoSEXT_H:
3598 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
3600 case RISCV::PseudoZEXT_H:
3601 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
3603 case RISCV::PseudoZEXT_W:
3604 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
3606 case RISCV::PseudoVMSGEU_VX:
3607 case RISCV::PseudoVMSGEU_VX_M:
3608 case RISCV::PseudoVMSGEU_VX_M_T:
3609 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3611 case RISCV::PseudoVMSGE_VX:
3612 case RISCV::PseudoVMSGE_VX_M:
3613 case RISCV::PseudoVMSGE_VX_M_T:
3614 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3616 case RISCV::PseudoVMSGE_VI:
3617 case RISCV::PseudoVMSLT_VI: {
3621 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3631 case RISCV::PseudoVMSGEU_VI:
3632 case RISCV::PseudoVMSLTU_VI: {
3639 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3650 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3665 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)
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)
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)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
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.
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)...
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)
@ 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.
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.
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.
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.