diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -739,6 +739,7 @@ #define GET_REGISTER_MATCHER #define GET_MATCHER_IMPLEMENTATION +#define GET_MNEMONIC_SPELL_CHECKER #include "RISCVGenAsmMatcher.inc" static Register convertFPR64ToFPR32(Register Reg) { @@ -775,6 +776,10 @@ return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); } +static std::string RISCVMnemonicSpellCheck(StringRef S, + const FeatureBitset &FBS, + unsigned VariantID = 0); + bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -791,8 +796,12 @@ return processInstruction(Inst, IDLoc, Operands, Out); case Match_MissingFeature: return Error(IDLoc, "instruction use requires an option to be enabled"); - case Match_MnemonicFail: - return Error(IDLoc, "unrecognized instruction mnemonic"); + case Match_MnemonicFail: { + FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); + std::string Suggestion = RISCVMnemonicSpellCheck( + ((RISCVOperand &)*Operands[0]).getToken(), FBS); + return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); + } case Match_InvalidOperand: { SMLoc ErrorLoc = IDLoc; if (ErrorInfo != ~0U) { diff --git a/llvm/test/MC/RISCV/invalid-instruction-spellcheck.s b/llvm/test/MC/RISCV/invalid-instruction-spellcheck.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/invalid-instruction-spellcheck.s @@ -0,0 +1,32 @@ +# RUN: not llvm-mc -triple=riscv32 < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-RV32,CHECK-RV32I %s +# RUN: not llvm-mc -triple=riscv64 < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-RV64,CHECK-RV64I %s +# RUN: not llvm-mc -triple=riscv32 -mattr=+f < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-RV32,CHECK-RV32IF %s +# RUN: not llvm-mc -triple=riscv64 -mattr=+f < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-RV64,CHECK-RV64IF %s + +# Tests for the mnemonic spell checker. Suggestions should only include those +# which are valid for the current set of features + +ad x1, x1, x1 +# CHECK-RV32: did you mean: add, addi, and, andi, la +# CHECK-RV64: did you mean: add, addi, addw, and, andi, la, ld, sd +# CHECK-NEXT: ad x1, x1, x1 + +fl ft0, 0(sp) +# CHECK-RV32I: did you mean: la, lb, lh, li, lw +# CHECK-RV32IF: did you mean: flw, la, lb, lh, li, lw +# CHECK-RV64I: did you mean: la, lb, ld, lh, li, lw +# CHECK-RV64IF: did you mean: flw, la, lb, ld, lh, li, lw +# CHECK-NEXT: fl ft0, 0(sp) + +addd x1, x1, x1 +# CHECK-RV32: did you mean: add, addi +# CHECK-RV64: did you mean: add, addi, addw +# CHECK-NEXT: addd x1, x1, x1 + +vm x0, x0 +# CHECK: did you mean: mv +# CHECK-NEXT: vm x0, x0