/// getEndLoc - Get the location of the last token of this operand.
SMLoc getEndLoc() const override { return EndLoc; }
+ /// getLocRange - Get the range between the first and last token of this
+ /// operand.
+ SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
+
/// isPPC64 - True if this operand is for an instruction in 64-bit mode.
bool isPPC64() const { return IsPPC64; }
}
}
+static std::string PPCMnemonicSpellCheck(StringRef S, uint64_t FBS,
+ unsigned VariantID = 0);
+
bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out, uint64_t &ErrorInfo,
return false;
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: {
+ uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
+ std::string Suggestion = PPCMnemonicSpellCheck(
+ ((PPCOperand &)*Operands[0]).getToken(), FBS);
+ return Error(IDLoc, "invalid instruction" + Suggestion,
+ ((PPCOperand &)*Operands[0]).getLocRange());
+ }
case Match_InvalidOperand: {
SMLoc ErrorLoc = IDLoc;
if (ErrorInfo != ~0ULL) {
#define GET_REGISTER_MATCHER
#define GET_MATCHER_IMPLEMENTATION
+#define GET_MNEMONIC_SPELL_CHECKER
#include "PPCGenAsmMatcher.inc"
// Define this matcher function after the auto-generated include so we
--- /dev/null
+# RUN: not llvm-mc -triple powerpc-unknown-unknown < %s 2>&1 | FileCheck %s
+
+# This tests the mnemonic spell checker.
+
+# First check what happens when an instruction is omitted:
+
+%r1, %r2, %r3
+
+# CHECK: error: unexpected token at start of statement
+# CHECK-NEXT: %r1, %r2, %r3
+# CHECK-NEXT: ^
+
+# We don't want to see a suggestion here; the edit distance is too large to
+# give sensible suggestions:
+
+aaaaaaaaaaaaaaa %r1, %r2, %r3
+
+# CHECK: error: invalid instruction
+# CHECK-NEXT: aaaaaaaaaaaaaaa %r1, %r2, %r3
+# CHECK-NEXT: ^
+
+# Check that we get one suggestion: 'vmaxfpg' is 1 edit away, i.e. an deletion.
+
+vmaxfpg %r1, %r2
+
+# CHECK: error: invalid instruction, did you mean: vmaxfp?
+# CHECK-NEXT: vmaxfpg %r1, %r2
+# CHECK-NEXT: ^
+
+# Check edit distance 1 and 2, just insertions:
+
+xsnmsubad %r1, %r2
+
+# CHECK: error: invalid instruction, did you mean: xsmsubadp, xsnmsubadp?
+# CHECK-NEXT: xsnmsubad %r1, %r2
+# CHECK-NEXT: ^
+
+# Check an instruction that is 2 edits away, and also has a lot of candidates:
+
+adXd %r1, %r2, %r3
+
+# CHECK: error: invalid instruction, did you mean: add, addc, adde, addi, fadd?
+# CHECK-NEXT: adXd %r1, %r2, %r3
+# CHECK-NEXT: ^