diff options
Diffstat (limited to 'lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp')
-rw-r--r-- | lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 114 |
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"); |