Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td @@ -489,24 +489,24 @@ let ParserMatchClass = VectorRegLoAsmOperand; } -class TypedVecListAsmOperand +class TypedVecListAsmOperand : AsmOperandClass { - let Name = "TypedVectorList" # count # "_" # lanes # kind; + let Name = "TypedVectorList" # count # "_" # lanes # eltsize; let PredicateMethod - = "isTypedVectorList<" # count # ", " # lanes # ", '" # kind # "'>"; + = "isTypedVectorList"; let RenderMethod = "addVectorList" # regsize # "Operands<" # count # ">"; } -class TypedVecListRegOperand +class TypedVecListRegOperand : RegisterOperand">; + # eltsize # "'>">; multiclass VectorList { // With implicit types (probably on instruction instead). E.g. { v0, v1 } def _64AsmOperand : AsmOperandClass { let Name = NAME # "64"; - let PredicateMethod = "isImplicitlyTypedVectorList<" # count # ">"; + let PredicateMethod = "isImplicitlyTypedVectorList"; let RenderMethod = "addVectorList64Operands<" # count # ">"; } @@ -516,7 +516,7 @@ def _128AsmOperand : AsmOperandClass { let Name = NAME # "128"; - let PredicateMethod = "isImplicitlyTypedVectorList<" # count # ">"; + let PredicateMethod = "isImplicitlyTypedVectorList"; let RenderMethod = "addVectorList128Operands<" # count # ">"; } @@ -527,25 +527,25 @@ // 64-bit register lists with explicit type. // { v0.8b, v1.8b } - def _8bAsmOperand : TypedVecListAsmOperand; + def _8bAsmOperand : TypedVecListAsmOperand; def "8b" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_8bAsmOperand"); } // { v0.4h, v1.4h } - def _4hAsmOperand : TypedVecListAsmOperand; + def _4hAsmOperand : TypedVecListAsmOperand; def "4h" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_4hAsmOperand"); } // { v0.2s, v1.2s } - def _2sAsmOperand : TypedVecListAsmOperand; + def _2sAsmOperand : TypedVecListAsmOperand; def "2s" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_2sAsmOperand"); } // { v0.1d, v1.1d } - def _1dAsmOperand : TypedVecListAsmOperand; + def _1dAsmOperand : TypedVecListAsmOperand; def "1d" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_1dAsmOperand"); } @@ -553,49 +553,49 @@ // 128-bit register lists with explicit type // { v0.16b, v1.16b } - def _16bAsmOperand : TypedVecListAsmOperand; + def _16bAsmOperand : TypedVecListAsmOperand; def "16b" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_16bAsmOperand"); } // { v0.8h, v1.8h } - def _8hAsmOperand : TypedVecListAsmOperand; + def _8hAsmOperand : TypedVecListAsmOperand; def "8h" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_8hAsmOperand"); } // { v0.4s, v1.4s } - def _4sAsmOperand : TypedVecListAsmOperand; + def _4sAsmOperand : TypedVecListAsmOperand; def "4s" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_4sAsmOperand"); } // { v0.2d, v1.2d } - def _2dAsmOperand : TypedVecListAsmOperand; + def _2dAsmOperand : TypedVecListAsmOperand; def "2d" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_2dAsmOperand"); } // { v0.b, v1.b } - def _bAsmOperand : TypedVecListAsmOperand; + def _bAsmOperand : TypedVecListAsmOperand; def "b" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_bAsmOperand"); } // { v0.h, v1.h } - def _hAsmOperand : TypedVecListAsmOperand; + def _hAsmOperand : TypedVecListAsmOperand; def "h" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_hAsmOperand"); } // { v0.s, v1.s } - def _sAsmOperand : TypedVecListAsmOperand; + def _sAsmOperand : TypedVecListAsmOperand; def "s" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_sAsmOperand"); } // { v0.d, v1.d } - def _dAsmOperand : TypedVecListAsmOperand; + def _dAsmOperand : TypedVecListAsmOperand; def "d" : TypedVecListRegOperand { let ParserMatchClass = !cast(NAME # "_dAsmOperand"); } Index: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -140,7 +140,9 @@ template OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands); OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands); - bool tryParseVectorList(OperandVector &Operands); + template + OperandMatchResultTy tryParseVectorList(OperandVector &Operands, + bool ExpectMatch = false); OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands); public: @@ -217,7 +219,8 @@ unsigned RegNum; unsigned Count; unsigned NumElements; - unsigned ElementKind; + unsigned ElementWidth; + RegKind RegisterKind; }; struct VectorIndexOp { @@ -861,18 +864,23 @@ /// Is this a vector list with the type implicit (presumably attached to the /// instruction itself)? - template bool isImplicitlyTypedVectorList() const { + template + bool isImplicitlyTypedVectorList() const { return Kind == k_VectorList && VectorList.Count == NumRegs && - !VectorList.ElementKind; + VectorList.NumElements == 0 && + VectorList.RegisterKind == VectorKind; } - template + template bool isTypedVectorList() const { if (Kind != k_VectorList) return false; if (VectorList.Count != NumRegs) return false; - if (VectorList.ElementKind != ElementKind) + if (VectorList.RegisterKind != VectorKind) + return false; + if (VectorList.ElementWidth != ElementWidth) return false; return VectorList.NumElements == NumElements; } @@ -1590,30 +1598,14 @@ static std::unique_ptr CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements, - unsigned ElementWidth, SMLoc S, SMLoc E, MCContext &Ctx) { + unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E, + MCContext &Ctx) { auto Op = make_unique(k_VectorList, Ctx); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.NumElements = NumElements; - switch (ElementWidth) { - case 0: - Op->VectorList.ElementKind = 0; - break; - case 8: - Op->VectorList.ElementKind = 'b'; - break; - case 16: - Op->VectorList.ElementKind = 'h'; - break; - case 32: - Op->VectorList.ElementKind = 's'; - break; - case 64: - Op->VectorList.ElementKind = 'd'; - break; - default: - llvm_unreachable("Unsupported elementwidth"); - } + Op->VectorList.ElementWidth = ElementWidth; + Op->VectorList.RegisterKind = RegisterKind; Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -2883,30 +2875,50 @@ return false; } -/// parseVectorList - Parse a vector list operand for vector instructions. -bool AArch64AsmParser::tryParseVectorList(OperandVector &Operands) { +template +OperandMatchResultTy +AArch64AsmParser::tryParseVectorList(OperandVector &Operands, + bool ExpectMatch) { MCAsmParser &Parser = getParser(); - assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket"); + if (!Parser.getTok().is(AsmToken::LCurly)) + return MatchOperand_NoMatch; // Wrapper around parse function - auto ParseVector = [this](int &Reg, StringRef &Kind, SMLoc Loc) { - if (tryParseVectorRegister(Reg, Kind, RegKind::NeonVector) == - MatchOperand_Success) { + auto ParseVector = [this, &Parser](int &Reg, StringRef &Kind, SMLoc Loc, + bool NoMatchIsError) { + auto RegTok = Parser.getTok(); + auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind); + if (ParseRes == MatchOperand_Success) { if (parseVectorKind(Kind, RegKind::NeonVector)) - return true; + return ParseRes; llvm_unreachable("Expected a valid vector kind"); } - Error(Loc, "vector register expected"); - return false; + if (RegTok.isNot(AsmToken::Identifier) || + ParseRes == MatchOperand_ParseFail || + (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) { + Error(Loc, "vector register expected"); + return MatchOperand_ParseFail; + } + + return MatchOperand_NoMatch; }; SMLoc S = getLoc(); + auto LCurly = Parser.getTok(); Parser.Lex(); // Eat left bracket token. + StringRef Kind; int FirstReg = -1; - if (!ParseVector(FirstReg, Kind, getLoc())) - return true; + auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch); + + // Put back the original left bracket if there was no match, so that + // different types of list-operands can be matched (e.g. SVE, Neon). + if (ParseRes == MatchOperand_NoMatch) + Parser.getLexer().UnLex(LCurly); + + if (ParseRes != MatchOperand_Success) + return ParseRes; int64_t PrevReg = FirstReg; unsigned Count = 1; @@ -2916,17 +2928,21 @@ StringRef NextKind; int Reg; - if (!ParseVector(Reg, NextKind, getLoc())) - return true; + ParseRes = ParseVector(Reg, NextKind, getLoc(), true); + if (ParseRes != MatchOperand_Success) + return ParseRes; // Any Kind suffices must match on all regs in the list. - if (Kind != NextKind) - return Error(Loc, "mismatched register size suffix"); + if (Kind != NextKind) { + Error(Loc, "mismatched register size suffix"); + return MatchOperand_ParseFail; + } unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg); if (Space == 0 || Space > 3) { - return Error(Loc, "invalid number of vectors"); + Error(Loc, "invalid number of vectors"); + return MatchOperand_ParseFail; } Count += Space; @@ -2936,16 +2952,22 @@ SMLoc Loc = getLoc(); StringRef NextKind; int Reg; - if (!ParseVector(Reg, NextKind, getLoc())) - return true; + ParseRes = ParseVector(Reg, NextKind, getLoc(), true); + if (ParseRes != MatchOperand_Success) + return ParseRes; + // Any Kind suffices must match on all regs in the list. - if (Kind != NextKind) - return Error(Loc, "mismatched register size suffix"); + if (Kind != NextKind) { + Error(Loc, "mismatched register size suffix"); + return MatchOperand_ParseFail; + } // Registers must be incremental (with wraparound at 31) if (getContext().getRegisterInfo()->getEncodingValue(Reg) != - (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) - return Error(Loc, "registers must be sequential"); + (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) { + Error(Loc, "registers must be sequential"); + return MatchOperand_ParseFail; + } PrevReg = Reg; ++Count; @@ -2953,27 +2975,31 @@ } if (parseToken(AsmToken::RCurly, "'}' expected")) - return true; + return MatchOperand_ParseFail; - if (Count > 4) - return Error(S, "invalid number of vectors"); + if (Count > 4) { + Error(S, "invalid number of vectors"); + return MatchOperand_ParseFail; + } unsigned NumElements = 0; unsigned ElementWidth = 0; if (!Kind.empty()) { - if (const auto &VK = parseVectorKind(Kind, RegKind::NeonVector)) + if (const auto &VK = parseVectorKind(Kind, VectorKind)) std::tie(NumElements, ElementWidth) = *VK; } Operands.push_back(AArch64Operand::CreateVectorList( - FirstReg, Count, NumElements, ElementWidth, S, getLoc(), getContext())); + FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(), + getContext())); - return false; + return MatchOperand_Success; } /// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions. bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) { - if (tryParseVectorList(Operands)) + auto ParseRes = tryParseVectorList(Operands, true); + if (ParseRes != MatchOperand_Success) return true; return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;