summaryrefslogtreecommitdiff
path: root/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp')
-rw-r--r--lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp114
1 files changed, 107 insertions, 7 deletions
diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 83764aab905..6e63783e564 100644
--- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -59,7 +59,12 @@ using namespace llvm;
namespace {
-enum class RegKind {Scalar, NeonVector, SVEDataVector};
+enum class RegKind {
+ Scalar,
+ NeonVector,
+ SVEDataVector,
+ SVEPredicateVector
+};
class AArch64AsmParser : public MCTargetAsmParser {
private:
@@ -134,6 +139,7 @@ private:
OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
template <bool ParseSuffix>
OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
+ OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
public:
enum AArch64MatchResultTy {
@@ -826,14 +832,26 @@ public:
Reg.RegNum);
}
- template <unsigned Class = AArch64::ZPRRegClassID>
- bool isSVEDataVectorReg() const {
- return (Kind == k_Register && Reg.Kind == RegKind::SVEDataVector) &&
+ template <unsigned Class> bool isSVEVectorReg() const {
+ RegKind RK;
+ switch (Class) {
+ case AArch64::ZPRRegClassID:
+ RK = RegKind::SVEDataVector;
+ break;
+ case AArch64::PPRRegClassID:
+ RK = RegKind::SVEPredicateVector;
+ break;
+ default:
+ llvm_unreachable("Unsupport register class");
+ }
+
+ return (Kind == k_Register && Reg.Kind == RK) &&
AArch64MCRegisterClasses[Class].contains(getReg());
}
- template <int ElementWidth> bool isSVEDataVectorRegOfWidth() const {
- return isSVEDataVectorReg() &&
+ template <int ElementWidth, unsigned Class>
+ bool isSVEVectorRegOfWidth() const {
+ return isSVEVectorReg<Class>() &&
(ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
}
@@ -1926,6 +1944,27 @@ static unsigned matchSVEDataVectorRegName(StringRef Name) {
.Default(0);
}
+static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
+ return StringSwitch<unsigned>(Name.lower())
+ .Case("p0", AArch64::P0)
+ .Case("p1", AArch64::P1)
+ .Case("p2", AArch64::P2)
+ .Case("p3", AArch64::P3)
+ .Case("p4", AArch64::P4)
+ .Case("p5", AArch64::P5)
+ .Case("p6", AArch64::P6)
+ .Case("p7", AArch64::P7)
+ .Case("p8", AArch64::P8)
+ .Case("p9", AArch64::P9)
+ .Case("p10", AArch64::P10)
+ .Case("p11", AArch64::P11)
+ .Case("p12", AArch64::P12)
+ .Case("p13", AArch64::P13)
+ .Case("p14", AArch64::P14)
+ .Case("p15", AArch64::P15)
+ .Default(0);
+}
+
static bool isValidSVEKind(StringRef Name) {
return StringSwitch<bool>(Name.lower())
.Case(".b", true)
@@ -1969,6 +2008,9 @@ unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
if ((RegNum = matchSVEDataVectorRegName(Name)))
return Kind == RegKind::SVEDataVector ? RegNum : 0;
+ if ((RegNum = matchSVEPredicateVectorRegName(Name)))
+ return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
+
if ((RegNum = MatchNeonVectorRegName(Name)))
return Kind == RegKind::NeonVector ? RegNum : 0;
@@ -2734,6 +2776,36 @@ AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
return MatchOperand_NoMatch;
}
+/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
+OperandMatchResultTy
+AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
+ // Check for a SVE predicate register specifier first.
+ const SMLoc S = getLoc();
+ StringRef Kind;
+ int RegNum = -1;
+ auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
+ if (Res != MatchOperand_Success)
+ return Res;
+
+ unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
+ .Case("", -1)
+ .Case(".b", 8)
+ .Case(".h", 16)
+ .Case(".s", 32)
+ .Case(".d", 64)
+ .Case(".q", 128)
+ .Default(0);
+
+ if (!ElementWidth)
+ return MatchOperand_NoMatch;
+
+ Operands.push_back(
+ AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
+ ElementWidth, S, getLoc(), getContext()));
+
+ return MatchOperand_Success;
+}
+
/// parseRegister - Parse a non-vector register operand.
bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
SMLoc S = getLoc();
@@ -2954,9 +3026,12 @@ AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
bool invertCondCode) {
MCAsmParser &Parser = getParser();
+
+ OperandMatchResultTy ResTy =
+ MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
+
// Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach.
- OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
if (ResTy == MatchOperand_Success)
return false;
// If there wasn't a custom match, try the generic matcher below. Otherwise,
@@ -3567,6 +3642,12 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
ComputeAvailableFeatures(STI->getFeatureBits()));
return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
}
+ case Match_InvalidSVEPredicateAnyReg:
+ case Match_InvalidSVEPredicateBReg:
+ case Match_InvalidSVEPredicateHReg:
+ case Match_InvalidSVEPredicateSReg:
+ case Match_InvalidSVEPredicateDReg:
+ return Error(Loc, "invalid predicate register.");
default:
llvm_unreachable("unexpected error code!");
}
@@ -3991,6 +4072,11 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidLabel:
case Match_InvalidComplexRotationEven:
case Match_InvalidComplexRotationOdd:
+ case Match_InvalidSVEPredicateAnyReg:
+ case Match_InvalidSVEPredicateBReg:
+ case Match_InvalidSVEPredicateHReg:
+ case Match_InvalidSVEPredicateSReg:
+ case Match_InvalidSVEPredicateDReg:
case Match_MSR:
case Match_MRS: {
if (ErrorInfo >= Operands.size())
@@ -4341,6 +4427,20 @@ bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
"sve vector register without type specifier expected");
}
+ if (RegNum == -1) {
+ StringRef Kind;
+ RegisterKind = RegKind::SVEPredicateVector;
+ OperandMatchResultTy Res =
+ tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
+
+ if (Res == MatchOperand_ParseFail)
+ return true;
+
+ if (Res == MatchOperand_Success && !Kind.empty())
+ return Error(SRegLoc,
+ "sve predicate register without type specifier expected");
+ }
+
if (RegNum == -1)
return Error(SRegLoc, "register name or alias expected");