]> granicus.if.org Git - llvm/commitdiff
[PowerPC, AsmParser] Enable the mnemonic spell corrector
authorHal Finkel <hfinkel@anl.gov>
Sat, 16 Dec 2017 02:42:18 +0000 (02:42 +0000)
committerHal Finkel <hfinkel@anl.gov>
Sat, 16 Dec 2017 02:42:18 +0000 (02:42 +0000)
r307148 added an assembly mnemonic spelling correction support and enabled it
on ARM. This enables that support on PowerPC as well.

Patch by Dmitry Venikov, thanks!

Differential Revision: https://reviews.llvm.org/D40552

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320911 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
test/MC/PowerPC/invalid-instructions-spellcheck.s [new file with mode: 0644]

index 2fbf51007c3df2ee5f23d54f4f0804bb4d7f5ea3..d6db354e02152e5dc21a9a8cbeebdd5de8488bb4 100644 (file)
@@ -393,6 +393,10 @@ public:
   /// 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; }
 
@@ -1268,6 +1272,9 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst,
   }
 }
 
+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,
@@ -1283,8 +1290,13 @@ bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     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) {
@@ -1920,6 +1932,7 @@ extern "C" void LLVMInitializePowerPCAsmParser() {
 
 #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
diff --git a/test/MC/PowerPC/invalid-instructions-spellcheck.s b/test/MC/PowerPC/invalid-instructions-spellcheck.s
new file mode 100644 (file)
index 0000000..cbf761f
--- /dev/null
@@ -0,0 +1,44 @@
+# 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: ^