have tblgen detect when an instruction would have matched, but
failed because a subtarget feature was not enabled.  Use this to
remove a bunch of hacks from the X86AsmParser for rejecting things
like popfl in 64-bit mode.  Previously these hacks weren't needed,
but were important to get a message better than "invalid instruction"
when used in the wrong mode.

This also fixes bugs where pushal would not be rejected correctly in
32-bit mode (just pusha).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113166 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 10c2b9c..5428876 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -615,28 +615,13 @@
 bool X86ATTAsmParser::
 ParseInstruction(StringRef Name, SMLoc NameLoc,
                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
-  // The various flavors of pushf and popf use Requires<In32BitMode> and
-  // Requires<In64BitMode>, but the assembler doesn't yet implement that.
-  // For now, just do a manual check to prevent silent misencoding.
-  if (Is64Bit) {
-    if (Name == "popfl")
-      return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
-    if (Name == "pushfl")
-      return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
-    if (Name == "pusha")
-      return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
-  } else {
-    if (Name == "popfq")
-      return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
-    if (Name == "pushfq")
-      return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
-  }
 
   // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
   // the form jrcxz is not allowed in 32-bit mode.
   if (Is64Bit) {
-    if (Name == "jcxz")
-      return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
+    // FIXME: We can do jcxz/jecxz, we just don't have the encoding right yet.
+    if (Name == "jcxz" || Name == "jecxz")
+      return Error(NameLoc, Name + " cannot be encoded in 64-bit mode");
   } else {
     if (Name == "jrcxz")
       return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
@@ -881,8 +866,15 @@
   assert(!Operands.empty() && "Unexpect empty operand list!");
 
   // First, try a direct match.
-  if (MatchInstructionImpl(Operands, Inst) == Match_Success)
+  switch (MatchInstructionImpl(Operands, Inst)) {
+  case Match_Success:
     return false;
+  case Match_MissingFeature:
+    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
+    return true;
+  default:
+    break;
+  }
 
   // FIXME: Ideally, we would only attempt suffix matches for things which are
   // valid prefixes, and we could just infer the right unambiguous
@@ -901,13 +893,13 @@
 
   // Check for the various suffix matches.
   Tmp[Base.size()] = 'b';
-  bool MatchB = MatchInstructionImpl(Operands, Inst) != Match_Success;
+  MatchResultTy MatchB = MatchInstructionImpl(Operands, Inst);
   Tmp[Base.size()] = 'w';
-  bool MatchW = MatchInstructionImpl(Operands, Inst) != Match_Success;
+  MatchResultTy MatchW = MatchInstructionImpl(Operands, Inst);
   Tmp[Base.size()] = 'l';
-  bool MatchL = MatchInstructionImpl(Operands, Inst) != Match_Success;
+  MatchResultTy MatchL = MatchInstructionImpl(Operands, Inst);
   Tmp[Base.size()] = 'q';
-  bool MatchQ = MatchInstructionImpl(Operands, Inst) != Match_Success;
+  MatchResultTy MatchQ = MatchInstructionImpl(Operands, Inst);
 
   // Restore the old token.
   Op->setTokenValue(Base);
@@ -915,23 +907,26 @@
   // If exactly one matched, then we treat that as a successful match (and the
   // instruction will already have been filled in correctly, since the failing
   // matches won't have modified it).
-  if (MatchB + MatchW + MatchL + MatchQ == 3)
+  unsigned NumSuccessfulMatches =
+    (MatchB == Match_Success) + (MatchW == Match_Success) +
+    (MatchL == Match_Success) + (MatchQ == Match_Success);
+  if (NumSuccessfulMatches == 1)
     return false;
 
-  // Otherwise, the match failed.
+  // Otherwise, the match failed, try to produce a decent error message.
 
   // If we had multiple suffix matches, then identify this as an ambiguous
   // match.
-  if (MatchB + MatchW + MatchL + MatchQ != 4) {
+  if (NumSuccessfulMatches > 1) {
     char MatchChars[4];
     unsigned NumMatches = 0;
-    if (!MatchB)
+    if (MatchB == Match_Success)
       MatchChars[NumMatches++] = 'b';
-    if (!MatchW)
+    if (MatchW == Match_Success)
       MatchChars[NumMatches++] = 'w';
-    if (!MatchL)
+    if (MatchL == Match_Success)
       MatchChars[NumMatches++] = 'l';
-    if (!MatchQ)
+    if (MatchQ == Match_Success)
       MatchChars[NumMatches++] = 'q';
 
     SmallString<126> Msg;
@@ -946,11 +941,26 @@
     }
     OS << ")";
     Error(IDLoc, OS.str());
-  } else {
-    // FIXME: We should give nicer diagnostics about the exact failure.
-    Error(IDLoc, "unrecognized instruction");
+    return true;
   }
-
+  
+  unsigned NumMatchFailures =
+    (MatchB == Match_Fail) + (MatchW == Match_Fail) +
+    (MatchL == Match_Fail) + (MatchQ == Match_Fail);
+  
+  
+  // If one instruction matched with a missing feature, report this as a
+  // missing feature.
+  if ((MatchB == Match_MissingFeature) + (MatchW == Match_MissingFeature) +
+      (MatchL == Match_MissingFeature) + (MatchQ == Match_MissingFeature) == 1&&
+      NumMatchFailures == 3) {
+    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
+    return true;
+  }
+  
+  // If all of these were an outright failure, report it in a useless way.
+  // FIXME: We should give nicer diagnostics about the exact failure.
+  Error(IDLoc, "unrecognized instruction");
   return true;
 }