46#define DEBUG_TYPE "riscv-asm-parser"
49 "Number of RISC-V Compressed instructions emitted");
58struct ParserOptionsSet {
66 ParserOptionsSet ParserOptions;
74 "do not have a target streamer");
80 unsigned Kind)
override;
89 bool MatchingInlineAsm)
override;
92 SMLoc &EndLoc)
override;
94 SMLoc &EndLoc)
override;
130 void emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
134 void emitPseudoExtend(
MCInst &Inst,
bool SignExtend, int64_t Width,
157#define GET_ASSEMBLER_HEADER
158#include "RISCVGenAsmMatcher.inc"
164 bool AllowParens =
false);
181 bool parseDirectiveOption();
182 bool parseDirectiveAttribute();
183 bool parseDirectiveInsn(
SMLoc L);
184 bool parseDirectiveVariantCC();
187 if (!(
getSTI().hasFeature(Feature))) {
195 if (
getSTI().hasFeature(Feature)) {
202 void pushFeatureBits() {
204 "These two stacks must be kept synchronized");
206 ParserOptionsStack.
push_back(ParserOptions);
209 bool popFeatureBits() {
211 "These two stacks must be kept synchronized");
212 if (FeatureBitStack.
empty())
224 std::unique_ptr<RISCVOperand> defaultMaskRegOp()
const;
225 std::unique_ptr<RISCVOperand> defaultFRMArgOp()
const;
228 enum RISCVMatchResultTy {
230 Match_RequiresEvenGPRs,
231#define GET_OPERAND_DIAGNOSTIC_TYPES
232#include "RISCVGenAsmMatcher.inc"
233#undef GET_OPERAND_DIAGNOSTIC_TYPES
236 static bool classifySymbolRef(
const MCExpr *Expr,
249 if (ABIName.endswith(
"f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
250 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
251 "doesn't support the F instruction set extension (ignoring "
253 }
else if (ABIName.endswith(
"d") &&
254 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
255 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
256 "doesn't support the D instruction set extension (ignoring "
319 SMLoc StartLoc, EndLoc;
325 struct SysRegOp SysReg;
326 struct VTypeOp VType;
328 struct FenceOp Fence;
331 RISCVOperand(KindTy K) :
Kind(
K) {}
336 StartLoc =
o.StartLoc;
339 case KindTy::Register:
342 case KindTy::Immediate:
345 case KindTy::FPImmediate:
351 case KindTy::SystemRegister:
366 bool isToken()
const override {
return Kind == KindTy::Token; }
367 bool isReg()
const override {
return Kind == KindTy::Register; }
368 bool isV0Reg()
const {
369 return Kind == KindTy::Register &&
Reg.RegNum == RISCV::V0;
371 bool isAnyReg()
const {
372 return Kind == KindTy::Register &&
373 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum) ||
374 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg.RegNum) ||
375 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg.RegNum));
377 bool isImm()
const override {
return Kind == KindTy::Immediate; }
378 bool isMem()
const override {
return false; }
379 bool isSystemRegister()
const {
return Kind == KindTy::SystemRegister; }
382 return Kind == KindTy::Register &&
383 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(
Reg.RegNum);
386 bool isGPRAsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
388 bool isGPRF64AsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
390 bool isGPRPF64AsFPR()
const {
return isGPR() &&
Reg.IsGPRAsFPR; }
392 static bool evaluateConstantImm(
const MCExpr *Expr, int64_t &Imm,
394 if (
auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
396 return RE->evaluateAsConstant(Imm);
399 if (
auto CE = dyn_cast<MCConstantExpr>(Expr)) {
401 Imm =
CE->getValue();
410 template <
int N>
bool isBareSimmNLsb0()
const {
415 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
418 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
426 bool isBareSymbol()
const {
430 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
432 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
436 bool isCallSymbol()
const {
440 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
442 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
447 bool isPseudoJumpSymbol()
const {
451 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
453 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
457 bool isTPRelAddSymbol()
const {
461 if (!
isImm() || evaluateConstantImm(getImm(), Imm, VK))
463 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
467 bool isCSRSystemRegister()
const {
return isSystemRegister(); }
469 bool isVTypeImm(
unsigned N)
const {
474 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
480 bool isVTypeI10()
const {
481 if (Kind == KindTy::Immediate)
482 return isVTypeImm(10);
483 return Kind == KindTy::VType;
485 bool isVTypeI11()
const {
486 if (Kind == KindTy::Immediate)
487 return isVTypeImm(11);
488 return Kind == KindTy::VType;
493 bool isFenceArg()
const {
return Kind == KindTy::Fence; }
496 bool isFRMArg()
const {
return Kind == KindTy::FRM; }
500 bool isLoadFPImm()
const {
503 if (Kind != KindTy::FPImmediate)
506 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
509 return Idx >= 0 &&
Idx != 1;
512 bool isImmXLenLI()
const {
517 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
523 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
526 bool isUImmLog2XLen()
const {
531 if (!evaluateConstantImm(getImm(), Imm, VK) ||
534 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
537 bool isUImmLog2XLenNonZero()
const {
542 if (!evaluateConstantImm(getImm(), Imm, VK) ||
547 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
550 bool isUImmLog2XLenHalf()
const {
555 if (!evaluateConstantImm(getImm(), Imm, VK) ||
558 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
561 template <
unsigned N>
bool IsUImm()
const {
566 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
570 bool isUImm2()
const {
return IsUImm<2>(); }
571 bool isUImm3()
const {
return IsUImm<3>(); }
572 bool isUImm5()
const {
return IsUImm<5>(); }
573 bool isUImm7()
const {
return IsUImm<7>(); }
575 bool isRnumArg()
const {
580 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
581 return IsConstantImm &&
Imm >= INT64_C(0) &&
Imm <= INT64_C(10) &&
585 bool isSImm5()
const {
590 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
591 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
595 bool isSImm6()
const {
600 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
601 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
605 bool isSImm6NonZero()
const {
610 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
611 return IsConstantImm &&
Imm != 0 &&
612 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
616 bool isCLUIImm()
const {
621 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
622 return IsConstantImm && (
Imm != 0) &&
623 (isUInt<5>(Imm) || (
Imm >= 0xfffe0 &&
Imm <= 0xfffff)) &&
627 bool isUImm2Lsb0()
const {
632 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
633 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
637 bool isUImm7Lsb00()
const {
642 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
643 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
647 bool isUImm8Lsb00()
const {
652 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
653 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
657 bool isUImm8Lsb000()
const {
662 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
663 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
667 bool isSImm9Lsb0()
const {
return isBareSimmNLsb0<9>(); }
669 bool isUImm9Lsb000()
const {
674 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
675 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
679 bool isUImm10Lsb00NonZero()
const {
684 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
685 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (
Imm != 0) &&
691 static int64_t fixImmediateForRV32(int64_t Imm,
bool IsRV64Imm) {
692 if (IsRV64Imm || !isUInt<32>(Imm))
694 return SignExtend64<32>(Imm);
697 bool isSImm12()
const {
703 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
705 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
707 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
714 bool isSImm12Lsb0()
const {
return isBareSimmNLsb0<12>(); }
716 bool isSImm12Lsb00000()
const {
721 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
722 return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
726 bool isSImm13Lsb0()
const {
return isBareSimmNLsb0<13>(); }
728 bool isSImm10Lsb0000NonZero()
const {
733 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
734 return IsConstantImm && (
Imm != 0) && isShiftedInt<6, 4>(Imm) &&
738 bool isUImm20LUI()
const {
744 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
745 if (!IsConstantImm) {
746 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
756 bool isUImm20AUIPC()
const {
762 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
763 if (!IsConstantImm) {
764 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
778 bool isSImm21Lsb0JAL()
const {
return isBareSimmNLsb0<21>(); }
780 bool isImmZero()
const {
785 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
789 bool isSImm5Plus1()
const {
794 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
795 return IsConstantImm &&
796 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
801 SMLoc getStartLoc()
const override {
return StartLoc; }
803 SMLoc getEndLoc()
const override {
return EndLoc; }
805 bool isRV64Imm()
const {
806 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
810 unsigned getReg()
const override {
811 assert(Kind == KindTy::Register &&
"Invalid type access!");
812 return Reg.RegNum.id();
816 assert(Kind == KindTy::SystemRegister &&
"Invalid type access!");
817 return StringRef(SysReg.Data, SysReg.Length);
820 const MCExpr *getImm()
const {
821 assert(Kind == KindTy::Immediate &&
"Invalid type access!");
826 assert(Kind == KindTy::FPImmediate &&
"Invalid type access!");
831 assert(Kind == KindTy::Token &&
"Invalid type access!");
835 unsigned getVType()
const {
836 assert(Kind == KindTy::VType &&
"Invalid type access!");
841 assert(Kind == KindTy::FRM &&
"Invalid type access!");
845 unsigned getFence()
const {
846 assert(Kind == KindTy::Fence &&
"Invalid type access!");
859 case KindTy::Immediate:
862 case KindTy::FPImmediate:
864 case KindTy::Register:
868 OS <<
"'" << getToken() <<
"'";
870 case KindTy::SystemRegister:
871 OS <<
"<sysreg: " << getSysReg() <<
'>';
880 roundingModeToString(getFRM());
891 static std::unique_ptr<RISCVOperand> createToken(
StringRef Str,
SMLoc S) {
892 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
899 static std::unique_ptr<RISCVOperand>
900 createReg(
unsigned RegNo,
SMLoc S,
SMLoc E,
bool IsGPRAsFPR =
false) {
901 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
902 Op->Reg.RegNum = RegNo;
903 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
909 static std::unique_ptr<RISCVOperand> createImm(
const MCExpr *Val,
SMLoc S,
911 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
913 Op->Imm.IsRV64 = IsRV64;
919 static std::unique_ptr<RISCVOperand> createFPImm(
uint64_t Val,
SMLoc S) {
920 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
927 static std::unique_ptr<RISCVOperand> createSysReg(
StringRef Str,
SMLoc S,
929 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
930 Op->SysReg.Data = Str.data();
931 Op->SysReg.Length = Str.size();
932 Op->SysReg.Encoding = Encoding;
938 static std::unique_ptr<RISCVOperand>
940 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
947 static std::unique_ptr<RISCVOperand> createFenceArg(
unsigned Val,
SMLoc S) {
948 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
955 static std::unique_ptr<RISCVOperand> createVType(
unsigned VTypeI,
SMLoc S) {
956 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
957 Op->VType.Val = VTypeI;
963 static void addExpr(
MCInst &Inst,
const MCExpr *Expr,
bool IsRV64Imm) {
964 assert(Expr &&
"Expr shouldn't be null!");
967 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
977 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
978 assert(
N == 1 &&
"Invalid number of operands!");
982 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
983 assert(
N == 1 &&
"Invalid number of operands!");
984 addExpr(Inst, getImm(), isRV64Imm());
987 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
988 assert(
N == 1 &&
"Invalid number of operands!");
990 addExpr(Inst, getImm(), isRV64Imm());
995 APFloat(APFloat::IEEEdouble(),
APInt(64, getFPConst())));
999 void addFenceArgOperands(
MCInst &Inst,
unsigned N)
const {
1000 assert(
N == 1 &&
"Invalid number of operands!");
1004 void addCSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
1005 assert(
N == 1 &&
"Invalid number of operands!");
1012 void addVTypeIOperands(
MCInst &Inst,
unsigned N)
const {
1013 assert(
N == 1 &&
"Invalid number of operands!");
1015 if (Kind == KindTy::Immediate) {
1017 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1018 (void)IsConstantImm;
1019 assert(IsConstantImm &&
"Invalid VTypeI Operand!");
1026 void addFRMArgOperands(
MCInst &Inst,
unsigned N)
const {
1027 assert(
N == 1 &&
"Invalid number of operands!");
1033#define GET_REGISTER_MATCHER
1034#define GET_SUBTARGET_FEATURE_NAME
1035#define GET_MATCHER_IMPLEMENTATION
1036#define GET_MNEMONIC_SPELL_CHECKER
1037#include "RISCVGenAsmMatcher.inc"
1040 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1041 return Reg - RISCV::F0_D + RISCV::F0_H;
1045 assert(
Reg >= RISCV::F0_D &&
Reg <= RISCV::F31_D &&
"Invalid register");
1046 return Reg - RISCV::F0_D + RISCV::F0_F;
1051 unsigned RegClassID;
1052 if (Kind == MCK_VRM2)
1053 RegClassID = RISCV::VRM2RegClassID;
1054 else if (Kind == MCK_VRM4)
1055 RegClassID = RISCV::VRM4RegClassID;
1056 else if (Kind == MCK_VRM8)
1057 RegClassID = RISCV::VRM8RegClassID;
1061 &RISCVMCRegisterClasses[RegClassID]);
1066 RISCVOperand &
Op =
static_cast<RISCVOperand &
>(AsmOp);
1068 return Match_InvalidOperand;
1072 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(
Reg);
1074 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
Reg);
1075 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(
Reg);
1079 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1080 (IsRegFPR64C &&
Kind == MCK_FPR32C)) {
1082 return Match_Success;
1086 if (IsRegFPR64 && Kind == MCK_FPR16) {
1088 return Match_Success;
1092 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1094 if (
Op.Reg.RegNum == 0)
1095 return Match_InvalidOperand;
1096 return Match_Success;
1098 return Match_InvalidOperand;
1101unsigned RISCVAsmParser::checkTargetMatchPredicate(
MCInst &Inst) {
1105 if (MCID.
operands()[
I].RegClass == RISCV::GPRPF64RegClassID) {
1110 if (((
Reg.id() - RISCV::X0) & 1) != 0)
1111 return Match_RequiresEvenGPRs;
1115 return Match_Success;
1118bool RISCVAsmParser::generateImmOutOfRangeError(
1120 Twine Msg =
"immediate must be an integer in the range") {
1125bool RISCVAsmParser::MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1129 bool MatchingInlineAsm) {
1139 if (validateInstruction(Inst,
Operands))
1141 return processInstruction(Inst, IDLoc,
Operands, Out);
1142 case Match_MissingFeature: {
1143 assert(MissingFeatures.
any() &&
"Unknown missing features!");
1144 bool FirstFeature =
true;
1145 std::string
Msg =
"instruction requires the following:";
1146 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
1147 if (MissingFeatures[i]) {
1148 Msg += FirstFeature ?
" " :
", ";
1150 FirstFeature =
false;
1153 return Error(IDLoc, Msg);
1155 case Match_MnemonicFail: {
1156 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1157 std::string Suggestion = RISCVMnemonicSpellCheck(
1158 ((RISCVOperand &)*
Operands[0]).getToken(), FBS, 0);
1159 return Error(IDLoc,
"unrecognized instruction mnemonic" + Suggestion);
1161 case Match_InvalidOperand: {
1162 SMLoc ErrorLoc = IDLoc;
1165 return Error(ErrorLoc,
"too few operands for instruction");
1168 if (ErrorLoc ==
SMLoc())
1171 return Error(ErrorLoc,
"invalid operand for instruction");
1178 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1179 SMLoc ErrorLoc = IDLoc;
1181 return Error(ErrorLoc,
"too few operands for instruction");
1187 case Match_RequiresEvenGPRs:
1189 "double precision floating point operands must use even "
1190 "numbered X register");
1191 case Match_InvalidImmXLenLI:
1194 return Error(ErrorLoc,
"operand must be a constant 64-bit integer");
1197 std::numeric_limits<int32_t>::min(),
1198 std::numeric_limits<uint32_t>::max());
1199 case Match_InvalidImmZero: {
1201 return Error(ErrorLoc,
"immediate must be zero");
1203 case Match_InvalidUImmLog2XLen:
1207 case Match_InvalidUImmLog2XLenNonZero:
1211 case Match_InvalidUImmLog2XLenHalf:
1215 case Match_InvalidUImm2:
1217 case Match_InvalidUImm2Lsb0:
1219 "immediate must be one of");
1220 case Match_InvalidUImm3:
1222 case Match_InvalidUImm5:
1224 case Match_InvalidUImm7:
1226 case Match_InvalidSImm5:
1229 case Match_InvalidSImm6:
1232 case Match_InvalidSImm6NonZero:
1233 return generateImmOutOfRangeError(
1235 "immediate must be non-zero in the range");
1236 case Match_InvalidCLUIImm:
1237 return generateImmOutOfRangeError(
1239 "immediate must be in [0xfffe0, 0xfffff] or");
1240 case Match_InvalidUImm7Lsb00:
1241 return generateImmOutOfRangeError(
1243 "immediate must be a multiple of 4 bytes in the range");
1244 case Match_InvalidUImm8Lsb00:
1245 return generateImmOutOfRangeError(
1247 "immediate must be a multiple of 4 bytes in the range");
1248 case Match_InvalidUImm8Lsb000:
1249 return generateImmOutOfRangeError(
1251 "immediate must be a multiple of 8 bytes in the range");
1252 case Match_InvalidSImm9Lsb0:
1253 return generateImmOutOfRangeError(
1255 "immediate must be a multiple of 2 bytes in the range");
1256 case Match_InvalidUImm9Lsb000:
1257 return generateImmOutOfRangeError(
1259 "immediate must be a multiple of 8 bytes in the range");
1260 case Match_InvalidUImm10Lsb00NonZero:
1261 return generateImmOutOfRangeError(
1263 "immediate must be a multiple of 4 bytes in the range");
1264 case Match_InvalidSImm10Lsb0000NonZero:
1265 return generateImmOutOfRangeError(
1267 "immediate must be a multiple of 16 bytes and non-zero in the range");
1268 case Match_InvalidSImm12:
1269 return generateImmOutOfRangeError(
1271 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1272 "integer in the range");
1273 case Match_InvalidSImm12Lsb0:
1274 return generateImmOutOfRangeError(
1276 "immediate must be a multiple of 2 bytes in the range");
1277 case Match_InvalidSImm12Lsb00000:
1278 return generateImmOutOfRangeError(
1280 "immediate must be a multiple of 32 bytes in the range");
1281 case Match_InvalidSImm13Lsb0:
1282 return generateImmOutOfRangeError(
1284 "immediate must be a multiple of 2 bytes in the range");
1285 case Match_InvalidUImm20LUI:
1287 "operand must be a symbol with "
1288 "%hi/%tprel_hi modifier or an integer in "
1290 case Match_InvalidUImm20AUIPC:
1291 return generateImmOutOfRangeError(
1293 "operand must be a symbol with a "
1294 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1295 "an integer in the range");
1296 case Match_InvalidSImm21Lsb0JAL:
1297 return generateImmOutOfRangeError(
1299 "immediate must be a multiple of 2 bytes in the range");
1300 case Match_InvalidCSRSystemRegister: {
1302 "operand must be a valid system register "
1303 "name or an integer in the range");
1305 case Match_InvalidLoadFPImm: {
1307 return Error(ErrorLoc,
"operand must be a valid floating-point constant");
1309 case Match_InvalidBareSymbol: {
1311 return Error(ErrorLoc,
"operand must be a bare symbol name");
1313 case Match_InvalidPseudoJumpSymbol: {
1315 return Error(ErrorLoc,
"operand must be a valid jump target");
1317 case Match_InvalidCallSymbol: {
1319 return Error(ErrorLoc,
"operand must be a bare symbol name");
1321 case Match_InvalidTPRelAddSymbol: {
1323 return Error(ErrorLoc,
"operand must be a symbol with %tprel_add modifier");
1325 case Match_InvalidRTZArg: {
1327 return Error(ErrorLoc,
"operand must be 'rtz' floating-point rounding mode");
1329 case Match_InvalidVTypeI: {
1334 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
1336 case Match_InvalidVMaskRegister: {
1338 return Error(ErrorLoc,
"operand must be v0.t");
1340 case Match_InvalidSImm5Plus1: {
1343 "immediate must be in the range");
1345 case Match_InvalidRnumArg: {
1362 assert(!(RegNo >= RISCV::F0_H && RegNo <= RISCV::F31_H));
1363 assert(!(RegNo >= RISCV::F0_F && RegNo <= RISCV::F31_F));
1365 static_assert(RISCV::F0_D < RISCV::F0_H,
"FPR matching must be updated");
1366 static_assert(RISCV::F0_D < RISCV::F0_F,
"FPR matching must be updated");
1367 if (RegNo == RISCV::NoRegister)
1369 if (IsRVE && RegNo >= RISCV::X16 && RegNo <= RISCV::X31)
1370 RegNo = RISCV::NoRegister;
1371 return RegNo == RISCV::NoRegister;
1377 return Error(StartLoc,
"invalid register name");
1384 const AsmToken &Tok = getParser().getTok();
1399 SMLoc FirstS = getLoc();
1400 bool HadParens =
false;
1407 size_t ReadCount = getLexer().peekTokens(Buf);
1410 LParen = getParser().getTok();
1415 switch (getLexer().getKind()) {
1418 getLexer().UnLex(LParen);
1425 if (RegNo == RISCV::NoRegister) {
1427 getLexer().UnLex(LParen);
1431 Operands.push_back(RISCVOperand::createToken(
"(", FirstS));
1435 Operands.push_back(RISCVOperand::createReg(RegNo, S,
E));
1440 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
1452 switch (getLexer().getKind()) {
1462 if (getParser().parseExpression(Res,
E))
1465 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1467 int64_t
Imm =
CE->getValue();
1468 if (isUInt<7>(Imm) && (Imm & 3) == 3) {
1469 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1478 if (getParser().parseIdentifier(Identifier))
1481 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1483 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1484 "Unexpected opcode");
1487 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1497 Error(S,
"opcode must be in the range [0, 127] and the lower 2 bits must be "
1507 switch (getLexer().getKind()) {
1517 if (getParser().parseExpression(Res))
1520 auto *
CE = dyn_cast<MCConstantExpr>(Res);
1522 int64_t
Imm =
CE->getValue();
1523 if (isUInt<12>(Imm)) {
1524 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1528 RISCVOperand::createSysReg(SysReg ? SysReg->Name :
"", S, Imm));
1533 Twine Msg =
"immediate must be an integer in the range";
1539 if (getParser().parseIdentifier(Identifier))
1542 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1544 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1546 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1547 Warning(S,
"'" + Identifier +
"' is a deprecated alias for '" +
1548 SysReg->Name +
"'");
1552 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
1553 Error(S,
"system register use requires an option to be enabled");
1557 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1561 Twine Msg =
"operand must be a valid system register name "
1562 "or an integer in the range";
1568 Twine Msg =
"immediate must be an integer in the range";
1583 if (
Identifier.compare_insensitive(
"inf") == 0) {
1586 getTok().getEndLoc(), isRV64()));
1587 }
else if (
Identifier.compare_insensitive(
"nan") == 0) {
1590 getTok().getEndLoc(), isRV64()));
1591 }
else if (
Identifier.compare_insensitive(
"min") == 0) {
1594 getTok().getEndLoc(), isRV64()));
1596 TokError(
"invalid floating point literal");
1610 TokError(
"invalid floating point immediate");
1615 APFloat RealVal(APFloat::IEEEdouble());
1617 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
1619 TokError(
"invalid floating point representation");
1624 RealVal.changeSign();
1626 Operands.push_back(RISCVOperand::createFPImm(
1627 RealVal.bitcastToAPInt().getZExtValue(), S));
1639 switch (getLexer().getKind()) {
1651 if (getParser().parseExpression(Res,
E))
1655 return parseOperandWithModifier(
Operands);
1658 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1668 Error(getLoc(),
"expected '%' for operand modifier");
1675 Error(getLoc(),
"expected valid identifier for operand modifier");
1681 Error(getLoc(),
"unrecognized operand modifier");
1687 Error(getLoc(),
"expected '('");
1693 if (getParser().parseParenExpression(SubExpr,
E)) {
1698 Operands.push_back(RISCVOperand::createImm(ModExpr, S,
E, isRV64()));
1710 AsmToken Tok = getLexer().getTok();
1712 if (getParser().parseIdentifier(Identifier))
1718 Error(getLoc(),
"'@plt' operand not valid for instruction");
1722 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1726 if (!isa<MCSymbolRefExpr>(V)) {
1727 getLexer().UnLex(Tok);
1735 switch (getLexer().getKind()) {
1737 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1750 if (getParser().parseExpression(Expr,
E))
1753 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1769 if (getParser().parseIdentifier(Identifier))
1778 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1781 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1791 if (getParser().parseExpression(Res,
E))
1794 if (Res->
getKind() != MCExpr::ExprKind::SymbolRef ||
1795 cast<MCSymbolRefExpr>(Res)->getKind() ==
1796 MCSymbolRefExpr::VariantKind::VK_PLT) {
1797 Error(S,
"operand must be a valid jump target");
1802 Operands.push_back(RISCVOperand::createImm(Res, S,
E, isRV64()));
1831 VTypeIElements.
push_back(getLexer().getTok());
1842 if (VTypeIElements.
size() == 7) {
1847 if (!
Name.consume_front(
"e"))
1850 if (
Name.getAsInteger(10, Sew))
1855 Name = VTypeIElements[2].getIdentifier();
1856 if (!
Name.consume_front(
"m"))
1859 bool Fractional =
Name.consume_front(
"f");
1861 if (
Name.getAsInteger(10, Lmul))
1867 Name = VTypeIElements[4].getIdentifier();
1871 else if (
Name ==
"tu")
1877 Name = VTypeIElements[6].getIdentifier();
1881 else if (
Name ==
"mu")
1890 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
1896 while (!VTypeIElements.
empty())
1906 if (!
Name.consume_back(
".t")) {
1907 Error(getLoc(),
"expected '.t' suffix");
1913 if (RegNo == RISCV::NoRegister)
1915 if (RegNo != RISCV::V0)
1920 Operands.push_back(RISCVOperand::createReg(RegNo, S,
E));
1932 if (RegNo == RISCV::NoRegister)
1937 Operands.push_back(RISCVOperand::createReg(
1938 RegNo, S,
E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
1944 TokError(
"operand must be a valid floating point rounding mode mnemonic");
1948 StringRef Str = getLexer().getTok().getIdentifier();
1952 TokError(
"operand must be a valid floating point rounding mode mnemonic");
1956 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
1962 const AsmToken &Tok = getLexer().getTok();
1968 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
1982 for (
char c : Str) {
2011 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2017 TokError(
"operand must be formed of letters selected in-order from 'iorw' "
2025 Error(getLoc(),
"expected '('");
2030 Operands.push_back(RISCVOperand::createToken(
"(", getLoc()));
2033 Error(getLoc(),
"expected register");
2038 Error(getLoc(),
"expected ')'");
2043 Operands.push_back(RISCVOperand::createToken(
")", getLoc()));
2068 std::unique_ptr<RISCVOperand> OptionalImmOp;
2075 SMLoc ImmStart = getLoc();
2076 if (getParser().parseIntToken(ImmVal,
2077 "expected '(' or optional integer offset"))
2082 SMLoc ImmEnd = getLoc();
2085 ImmStart, ImmEnd, isRV64());
2089 Error(getLoc(), OptionalImmOp ?
"expected '(' after optional integer offset"
2090 :
"expected '(' or optional integer offset");
2096 Error(getLoc(),
"expected register");
2101 Error(getLoc(),
"expected ')'");
2107 if (OptionalImmOp && !OptionalImmOp->isImmZero()) {
2108 Error(OptionalImmOp->getStartLoc(),
"optional integer offset must be 0",
2109 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2123 MatchOperandParserImpl(
Operands, Mnemonic,
true);
2142 Error(getLoc(),
"unknown operand");
2155 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2156 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2157 if (Assembler !=
nullptr) {
2165 Operands.push_back(RISCVOperand::createToken(
Name, NameLoc));
2188 SMLoc Loc = getLexer().getLoc();
2189 getParser().eatToEndOfStatement();
2190 return Error(Loc,
"unexpected token");
2197bool RISCVAsmParser::classifySymbolRef(
const MCExpr *Expr,
2201 if (
const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2202 Kind = RE->getKind();
2203 Expr = RE->getSubExpr();
2213bool RISCVAsmParser::ParseDirective(
AsmToken DirectiveID) {
2220 if (IDVal ==
".option")
2221 return parseDirectiveOption();
2222 if (IDVal ==
".attribute")
2223 return parseDirectiveAttribute();
2224 if (IDVal ==
".insn")
2225 return parseDirectiveInsn(DirectiveID.
getLoc());
2226 if (IDVal ==
".variant_cc")
2227 return parseDirectiveVariantCC();
2232bool RISCVAsmParser::parseDirectiveOption() {
2243 if (Option ==
"push") {
2247 getTargetStreamer().emitDirectiveOptionPush();
2252 if (Option ==
"pop") {
2257 getTargetStreamer().emitDirectiveOptionPop();
2258 if (popFeatureBits())
2259 return Error(StartLoc,
".option pop with no .option push");
2264 if (Option ==
"rvc") {
2268 getTargetStreamer().emitDirectiveOptionRVC();
2269 setFeatureBits(RISCV::FeatureStdExtC,
"c");
2273 if (Option ==
"norvc") {
2277 getTargetStreamer().emitDirectiveOptionNoRVC();
2278 clearFeatureBits(RISCV::FeatureStdExtC,
"c");
2279 clearFeatureBits(RISCV::FeatureExtZca,
"+experimental-zca");
2283 if (Option ==
"pic") {
2287 getTargetStreamer().emitDirectiveOptionPIC();
2288 ParserOptions.IsPicEnabled =
true;
2292 if (Option ==
"nopic") {
2296 getTargetStreamer().emitDirectiveOptionNoPIC();
2297 ParserOptions.IsPicEnabled =
false;
2301 if (Option ==
"relax") {
2305 getTargetStreamer().emitDirectiveOptionRelax();
2306 setFeatureBits(RISCV::FeatureRelax,
"relax");
2310 if (Option ==
"norelax") {
2314 getTargetStreamer().emitDirectiveOptionNoRelax();
2315 clearFeatureBits(RISCV::FeatureRelax,
"relax");
2321 "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
2330bool RISCVAsmParser::parseDirectiveAttribute() {
2337 std::optional<unsigned>
Ret =
2340 Error(TagLoc,
"attribute name not recognised: " +
Name);
2353 if (
check(!CE, TagLoc,
"expected numeric constant"))
2356 Tag =
CE->getValue();
2363 int64_t IntegerValue = 0;
2364 bool IsIntegerValue =
true;
2369 IsIntegerValue =
false;
2372 if (IsIntegerValue) {
2379 return Error(ValueExprLoc,
"expected numeric constant");
2380 IntegerValue =
CE->getValue();
2393 getTargetStreamer().emitAttribute(
Tag, IntegerValue);
2395 getTargetStreamer().emitTextAttribute(
Tag, StringValue);
2400 clearFeatureBits(Feature.Value, Feature.Key);
2409 OutputErrMsg <<
"invalid arch name '" << Arch <<
"', "
2410 << ErrMsg.getMessage();
2413 return Error(ValueExprLoc, OutputErrMsg.str());
2415 auto &ISAInfo = *ParseResult;
2418 if (ISAInfo->hasExtension(Feature.Key))
2419 setFeatureBits(Feature.Value, Feature.Key);
2421 if (ISAInfo->getXLen() == 32)
2422 clearFeatureBits(RISCV::Feature64Bit,
"64bit");
2423 else if (ISAInfo->getXLen() == 64)
2424 setFeatureBits(RISCV::Feature64Bit,
"64bit");
2426 return Error(ValueExprLoc,
"bad arch string " + Arch);
2429 getTargetStreamer().emitTextAttribute(
Tag, ISAInfo->toString());
2437bool RISCVAsmParser::parseDirectiveInsn(
SMLoc L) {
2444 return Error(ErrorLoc,
"expected instruction format");
2446 if (Format !=
"r" && Format !=
"r4" && Format !=
"i" && Format !=
"b" &&
2447 Format !=
"sb" && Format !=
"u" && Format !=
"j" && Format !=
"uj" &&
2449 return Error(ErrorLoc,
"invalid instruction format");
2451 std::string FormatName = (
".insn_" +
Format).str();
2468bool RISCVAsmParser::parseDirectiveVariantCC() {
2470 if (getParser().parseIdentifier(
Name))
2471 return TokError(
"expected symbol name");
2474 getTargetStreamer().emitDirectiveVariantCC(
2475 *getContext().getOrCreateSymbol(
Name));
2483 ++RISCVNumInstrsCompressed;
2494 switch (Inst.getOpndKind()) {
2524 unsigned SecondOpcode,
SMLoc IDLoc,
2538 const MCExpr *RefToLinkTmpLabel =
2545 .addExpr(RefToLinkTmpLabel));
2548void RISCVAsmParser::emitLoadLocalAddress(
MCInst &Inst,
SMLoc IDLoc,
2559 RISCV::ADDI, IDLoc, Out);
2562void RISCVAsmParser::emitLoadAddress(
MCInst &Inst,
SMLoc IDLoc,
2575 unsigned SecondOpcode;
2577 if (ParserOptions.IsPicEnabled) {
2578 SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2581 SecondOpcode = RISCV::ADDI;
2584 emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
2587void RISCVAsmParser::emitLoadTLSIEAddress(
MCInst &Inst,
SMLoc IDLoc,
2597 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2599 SecondOpcode, IDLoc, Out);
2602void RISCVAsmParser::emitLoadTLSGDAddress(
MCInst &Inst,
SMLoc IDLoc,
2613 RISCV::ADDI, IDLoc, Out);
2616void RISCVAsmParser::emitLoadStoreSymbol(
MCInst &Inst,
unsigned Opcode,
2626 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
2628 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
2632 Opcode, IDLoc, Out);
2635void RISCVAsmParser::emitPseudoExtend(
MCInst &Inst,
bool SignExtend,
2636 int64_t Width,
SMLoc IDLoc,
2648 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
2649 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
2651 assert(ShAmt > 0 &&
"Shift amount must be non-zero.");
2664void RISCVAsmParser::emitVMSGE(
MCInst &Inst,
unsigned Opcode,
SMLoc IDLoc,
2675 .addReg(RISCV::NoRegister));
2686 "The destination register should not be V0.");
2695 .addReg(RISCV::V0));
2703 "The destination register should be V0.");
2705 "The temporary vector register should not be V0.");
2722 "The temporary vector register should not be V0.");
2727 .addReg(RISCV::NoRegister));
2735 .addReg(RISCV::V0));
2743bool RISCVAsmParser::checkPseudoAddTPRel(
MCInst &Inst,
2745 assert(Inst.
getOpcode() == RISCV::PseudoAddTPRel &&
"Invalid instruction");
2748 SMLoc ErrorLoc = ((RISCVOperand &)*
Operands[3]).getStartLoc();
2749 return Error(ErrorLoc,
"the second input operand must be tp/x4 when using "
2750 "%tprel_add modifier");
2756std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp()
const {
2757 return RISCVOperand::createReg(RISCV::NoRegister,
llvm::SMLoc(),
2761std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp()
const {
2762 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
2766bool RISCVAsmParser::validateInstruction(
MCInst &Inst,
2768 if (Inst.
getOpcode() == RISCV::PseudoVMSGEU_VX_M_T ||
2769 Inst.
getOpcode() == RISCV::PseudoVMSGE_VX_M_T) {
2772 if (DestReg == TempReg) {
2774 return Error(Loc,
"The temporary vector register cannot be the same as "
2775 "the destination register.");
2781 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
2782 Opcode == RISCV::TH_LWD) {
2787 if (Rs1 == Rd1 && Rs1 == Rd2) {
2789 return Error(Loc,
"The source register and destination registers "
2790 "cannot be equal.");
2794 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
2795 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
2796 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
2801 return Error(Loc,
"Operand must be constant 3.");
2804 return Error(Loc,
"Operand must be constant 4.");
2817 if (DestReg == CheckReg)
2818 return Error(Loc,
"The destination vector register group cannot overlap"
2819 " the source vector register group.");
2823 if (DestReg == CheckReg)
2824 return Error(Loc,
"The destination vector register group cannot overlap"
2825 " the source vector register group.");
2830 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
2831 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
2832 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
2833 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
2834 Opcode == RISCV::VMERGE_VXM)
2835 return Error(Loc,
"The destination vector register group cannot be V0.");
2842 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
2843 "Unexpected register for mask operand");
2845 if (DestReg == CheckReg)
2846 return Error(Loc,
"The destination vector register group cannot overlap"
2847 " the mask register.");
2852bool RISCVAsmParser::processInstruction(
MCInst &Inst,
SMLoc IDLoc,
2860 case RISCV::PseudoLI: {
2877 Imm = SignExtend64<32>(Imm);
2878 emitLoadImm(
Reg, Imm, Out);
2881 case RISCV::PseudoLLA:
2882 emitLoadLocalAddress(Inst, IDLoc, Out);
2884 case RISCV::PseudoLA:
2885 emitLoadAddress(Inst, IDLoc, Out);
2887 case RISCV::PseudoLA_TLS_IE:
2888 emitLoadTLSIEAddress(Inst, IDLoc, Out);
2890 case RISCV::PseudoLA_TLS_GD:
2891 emitLoadTLSGDAddress(Inst, IDLoc, Out);
2893 case RISCV::PseudoLB:
2894 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out,
false);
2896 case RISCV::PseudoLBU:
2897 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out,
false);
2899 case RISCV::PseudoLH:
2900 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out,
false);
2902 case RISCV::PseudoLHU:
2903 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out,
false);
2905 case RISCV::PseudoLW:
2906 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out,
false);
2908 case RISCV::PseudoLWU:
2909 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out,
false);
2911 case RISCV::PseudoLD:
2912 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out,
false);
2914 case RISCV::PseudoFLH:
2915 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out,
true);
2917 case RISCV::PseudoFLW:
2918 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out,
true);
2920 case RISCV::PseudoFLD:
2921 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out,
true);
2923 case RISCV::PseudoSB:
2924 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out,
true);
2926 case RISCV::PseudoSH:
2927 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out,
true);
2929 case RISCV::PseudoSW:
2930 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out,
true);
2932 case RISCV::PseudoSD:
2933 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out,
true);
2935 case RISCV::PseudoFSH:
2936 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out,
true);
2938 case RISCV::PseudoFSW:
2939 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out,
true);
2941 case RISCV::PseudoFSD:
2942 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out,
true);
2944 case RISCV::PseudoAddTPRel:
2945 if (checkPseudoAddTPRel(Inst,
Operands))
2948 case RISCV::PseudoSEXT_B:
2949 emitPseudoExtend(Inst,
true, 8, IDLoc, Out);
2951 case RISCV::PseudoSEXT_H:
2952 emitPseudoExtend(Inst,
true, 16, IDLoc, Out);
2954 case RISCV::PseudoZEXT_H:
2955 emitPseudoExtend(Inst,
false, 16, IDLoc, Out);
2957 case RISCV::PseudoZEXT_W:
2958 emitPseudoExtend(Inst,
false, 32, IDLoc, Out);
2960 case RISCV::PseudoVMSGEU_VX:
2961 case RISCV::PseudoVMSGEU_VX_M:
2962 case RISCV::PseudoVMSGEU_VX_M_T:
2963 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
2965 case RISCV::PseudoVMSGE_VX:
2966 case RISCV::PseudoVMSGE_VX_M:
2967 case RISCV::PseudoVMSGE_VX_M_T:
2968 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
2970 case RISCV::PseudoVMSGE_VI:
2971 case RISCV::PseudoVMSLT_VI: {
2975 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
2984 case RISCV::PseudoVMSGEU_VI:
2985 case RISCV::PseudoVMSLTU_VI: {
2992 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3002 unsigned Opc = Inst.
getOpcode() == RISCV::PseudoVMSGEU_VI
3016 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
static bool matchRegisterNameHelper(bool IsRVE, MCRegister &RegNo, StringRef Name)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser()
static MCRegister convertFPR64ToFPR32(MCRegister Reg)
static MCRegister convertFPR64ToFPR16(MCRegister Reg)
static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg, unsigned Kind)
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 SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
Class for arbitrary precision integers.
Target independent representation for an assembler token.
int64_t getIntVal() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
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
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
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 ...
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
bool isVariable() const
isVariable - Check if this is a variable symbol.
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool ParseDirective(AsmToken DirectiveID)=0
ParseDirective - Parse 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
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 ...
virtual OperandMatchResultTy tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
Target specific streamer interface.
This represents an "assembler immediate".
uint32_t getRefKind() const
static bool isSupportedExtensionFeature(StringRef Ext)
static llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true, bool IgnoreUnknown=false)
Parse RISCV 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)
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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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.
const CustomOperand< const MCSubtargetInfo & > Msg[]
std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, StringRef ABIName)
const TagNameMap & getRISCVAttributeTags()
static RoundingMode stringToRoundingMode(StringRef Str)
static VConstraintType getConstraint(uint64_t TSFlags)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures)
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)
@ CE
Windows NT (Windows on ARM)
Reg
All possible values of the reg field in the ModR/M byte.
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.
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.