diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -157,7 +157,8 @@ bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands); void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S); - AArch64CC::CondCode parseCondCodeString(StringRef Cond); + AArch64CC::CondCode parseCondCodeString(StringRef Cond, + std::string &Suggestion); bool parseCondCode(OperandVector &Operands, bool invertCondCode); unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind); bool parseRegister(OperandVector &Operands); @@ -3029,8 +3030,10 @@ return MatchOperand_Success; } -/// parseCondCodeString - Parse a Condition Code string. -AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) { +/// parseCondCodeString - Parse a Condition Code string, optionally returning a +/// suggestion to help common typos. +AArch64CC::CondCode +AArch64AsmParser::parseCondCodeString(StringRef Cond, std::string &Suggestion) { AArch64CC::CondCode CC = StringSwitch(Cond.lower()) .Case("eq", AArch64CC::EQ) .Case("ne", AArch64CC::NE) @@ -3053,7 +3056,7 @@ .Default(AArch64CC::Invalid); if (CC == AArch64CC::Invalid && - getSTI().getFeatureBits()[AArch64::FeatureSVE]) + getSTI().getFeatureBits()[AArch64::FeatureSVE]) { CC = StringSwitch(Cond.lower()) .Case("none", AArch64CC::EQ) .Case("any", AArch64CC::NE) @@ -3067,6 +3070,9 @@ .Case("tstop", AArch64CC::LT) .Default(AArch64CC::Invalid); + if (CC == AArch64CC::Invalid && Cond.lower() == "nfirst") + Suggestion = "nfrst"; + } return CC; } @@ -3078,9 +3084,14 @@ assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); StringRef Cond = Tok.getString(); - AArch64CC::CondCode CC = parseCondCodeString(Cond); - if (CC == AArch64CC::Invalid) - return TokError("invalid condition code"); + std::string Suggestion; + AArch64CC::CondCode CC = parseCondCodeString(Cond, Suggestion); + if (CC == AArch64CC::Invalid) { + std::string Msg = "invalid condition code"; + if (!Suggestion.empty()) + Msg += ", did you mean " + Suggestion + "?"; + return TokError(Msg); + } Lex(); // Eat identifier token. if (invertCondCode) { @@ -4545,9 +4556,14 @@ SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() + (Head.data() - Name.data())); - AArch64CC::CondCode CC = parseCondCodeString(Head); - if (CC == AArch64CC::Invalid) - return Error(SuffixLoc, "invalid condition code"); + std::string Suggestion; + AArch64CC::CondCode CC = parseCondCodeString(Head, Suggestion); + if (CC == AArch64CC::Invalid) { + std::string Msg = "invalid condition code"; + if (!Suggestion.empty()) + Msg += ", did you mean " + Suggestion + "?"; + return Error(SuffixLoc, Msg); + } Operands.push_back(AArch64Operand::CreateToken(".", SuffixLoc, getContext(), /*IsSuffix=*/true)); Operands.push_back( diff --git a/llvm/test/MC/AArch64/SVE/condtion-code-diagnostics.s b/llvm/test/MC/AArch64/SVE/condtion-code-diagnostics.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE/condtion-code-diagnostics.s @@ -0,0 +1,9 @@ +// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=+sve < %s 2>&1 | FileCheck %s + +//------------------------------------------------------------------------------ +// Condition code diagnostics for SVE +//------------------------------------------------------------------------------ + + b.nfirst lbl +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid condition code, did you mean nfrst? +// CHECK-NEXT: b.nfirst lbl