Index: include/llvm/AsmParser/MnemonicSpellCheck.h =================================================================== --- /dev/null +++ include/llvm/AsmParser/MnemonicSpellCheck.h @@ -0,0 +1,42 @@ + +// Simple implementation of Levenshtein Distance calculation. +unsigned CalcLevenshteinDist(std::string S, std::string T) { + const unsigned N = S.size() + 1; + const unsigned M = T.size() + 1; + + if (!S.size()) return M; + if (!T.size()) return N; + + std::vector >Mat(M, std::vector(N)); + + for (unsigned i = 0; i StringOffset; std::string AggregateString; public: + StringMap StringOffset; + bool Empty() const { return StringOffset.empty(); } unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -8985,6 +8985,8 @@ return PlainMatchResult; } +std::string MnemonicSpellCheck(std::string S); + static const char *getSubtargetFeatureName(uint64_t Val); bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, @@ -9078,9 +9080,12 @@ return Error(ErrorLoc, "invalid operand for instruction"); } - case Match_MnemonicFail: - return Error(IDLoc, "invalid instruction", + case Match_MnemonicFail: { + std::string Suggestion = MnemonicSpellCheck( + std::string(((ARMOperand &)*Operands[0]).getToken())); + return Error(IDLoc, "invalid instruction, " + Suggestion, ((ARMOperand &)*Operands[0]).getLocRange()); + } case Match_RequiresNotITBlock: return Error(IDLoc, "flag setting instruction only valid outside IT block"); case Match_RequiresITBlock: @@ -10183,6 +10188,7 @@ #define GET_SUBTARGET_FEATURE_NAME #define GET_MATCHER_IMPLEMENTATION #include "ARMGenAsmMatcher.inc" +#include "llvm/AsmParser/MnemonicSpellCheck.h" // FIXME: This structure should be moved inside ARMTargetParser // when we start to table-generate them, and we can use the ARM Index: utils/TableGen/AsmMatcherEmitter.cpp =================================================================== --- utils/TableGen/AsmMatcherEmitter.cpp +++ utils/TableGen/AsmMatcherEmitter.cpp @@ -2880,6 +2880,16 @@ StringTable.GetOrAddStringOffset(LenMnemonic, false)); } + OS << "static std::string MnemonicStringTable[] = {\n"; + for (const auto &MI : StringTable.StringOffset) { + std::string first(MI.first()); + OS << "\"" << first.erase(0, 1) << "\",\n"; + } + OS << "};\n\n"; + + OS << "static unsigned MnemonicStringTableSize = " << + StringTable.StringOffset.size() << ";\n\n"; + OS << "static const char *const MnemonicTable =\n"; StringTable.EmitString(OS); OS << ";\n\n";