[llvm-commits] [llvm] r78522 - /llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp

Daniel Dunbar daniel at zuster.org
Sat Aug 8 21:00:06 PDT 2009


Author: ddunbar
Date: Sat Aug  8 23:00:06 2009
New Revision: 78522

URL: http://llvm.org/viewvc/llvm-project?rev=78522&view=rev
Log:
llvm-mc/AsmParser: Sketch infrastructure for ordering instructions & detecting
ambiguities.
 - Currently there are 483 ambiguities to resolve. :)

Modified:
    llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp

Modified: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp?rev=78522&r1=78521&r2=78522&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp Sat Aug  8 23:00:06 2009
@@ -78,6 +78,7 @@
 #include "Record.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -88,8 +89,8 @@
 
 namespace {
 static cl::opt<std::string>
-MatchOneInstr("match-one-instr", cl::desc("Match only the named instruction"),
-              cl::init(""));
+MatchPrefix("match-prefix", cl::init(""),
+            cl::desc("Only match instructions with the given prefix"));
 }
 
 /// FlattenVariants - Flatten an .td file assembly string by selecting the
@@ -276,11 +277,16 @@
 /// ClassInfo - Helper class for storing the information about a particular
 /// class of operands which can be matched.
 struct ClassInfo {
-  enum {
+  enum ClassInfoKind {
     Token, ///< The class for a particular token.
     Register, ///< A register class.
-    User ///< A user defined class.
-  } Kind;
+    UserClass0 ///< The (first) user defined class, subsequent user defined
+               /// classes are UserClass0+1, and so on.
+  };
+
+  /// Kind - The class kind, which is either a predefined kind, or (UserClass0 +
+  /// N) for the Nth user defined class.
+  unsigned Kind;
 
   /// Name - The class name, suitable for use as an enum.
   std::string Name;
@@ -297,6 +303,29 @@
   /// RenderMethod - The name of the operand method to add this operand to an
   /// MCInst; this is not valid for Token kinds.
   std::string RenderMethod;
+
+  /// operator< - Compare two classes.
+  bool operator<(const ClassInfo &RHS) const {
+    // Incompatible kinds are comparable.
+    if (Kind != RHS.Kind)
+      return Kind < RHS.Kind;
+
+    switch (Kind) {
+    case Token:
+      // Tokens are always comparable.
+      //
+      // FIXME: Compare by enum value.
+      return ValueName < RHS.ValueName;
+
+    case Register:
+      // FIXME: Compare by subset relation.
+      return false;
+
+    default:
+      // FIXME: Allow user defined relation.
+      return false;
+    }
+  }
 };
 
 /// InstructionInfo - Helper class for storing the necessary information for an
@@ -331,6 +360,38 @@
   /// function.
   std::string ConversionFnKind;
 
+  /// operator< - Compare two instructions.
+  bool operator<(const InstructionInfo &RHS) const {
+    // Order first by the number of operands (which is unambiguous).
+    if (Operands.size() != RHS.Operands.size())
+      return Operands.size() < RHS.Operands.size();
+    
+    // Otherwise, order by lexicographic comparison of tokens and operand kinds
+    // (these can never be ambiguous).
+    for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+      if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
+          Operands[i].Class->Kind == ClassInfo::Token)
+        if (*Operands[i].Class < *RHS.Operands[i].Class)
+          return true;
+    
+    // Finally, order by the component wise comparison of operand classes. We
+    // don't want to rely on the lexigraphic ordering of elements, so we define
+    // only define the ordering when it is unambiguous. That is, when some pair
+    // compares less than and no pair compares greater than.
+
+    // Check that no pair compares greater than.
+    for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+      if (*RHS.Operands[i].Class < *Operands[i].Class)
+        return false;
+
+    // Otherwise, return true if some pair compares less than.
+    for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+      if (*Operands[i].Class < *RHS.Operands[i].Class)
+        return true;
+
+    return false;
+  }
+
 public:
   void dump();
 };
@@ -460,7 +521,10 @@
     if (ClassName == "Reg") {
       Entry->Kind = ClassInfo::Register;
     } else {
-      Entry->Kind = ClassInfo::User;
+      if (ClassName == "Mem")
+        Entry->Kind = ClassInfo::UserClass0;
+      else
+        Entry->Kind = ClassInfo::UserClass0 + 1;        
     }
     Entry->Name = "MCK_" + ClassName;
     Entry->ValueName = OI.Rec->getName();
@@ -479,7 +543,7 @@
        it != ie; ++it) {
     const CodeGenInstruction &CGI = it->second;
 
-    if (!MatchOneInstr.empty() && it->first != MatchOneInstr)
+    if (!StringRef(it->first).startswith(MatchPrefix))
       continue;
 
     OwningPtr<InstructionInfo> II(new InstructionInfo);
@@ -537,9 +601,9 @@
   }
 }
 
-static void ConstructConversionFunctions(CodeGenTarget &Target,
-                                         std::vector<InstructionInfo*> &Infos,
-                                         raw_ostream &OS) {
+static void EmitConvertToMCInst(CodeGenTarget &Target,
+                                std::vector<InstructionInfo*> &Infos,
+                                raw_ostream &OS) {
   // Write the convert function to a separate stream, so we can drop it after
   // the enum.
   std::string ConvertFnBody;
@@ -902,6 +966,10 @@
   AsmMatcherInfo Info;
   Info.BuildInfo(Target);
 
+  // Sort the instruction table using the partial order on classes.
+  std::sort(Info.Instructions.begin(), Info.Instructions.end(),
+            less_ptr<InstructionInfo>());
+  
   DEBUG_WITH_TYPE("instruction_info", {
       for (std::vector<InstructionInfo*>::iterator 
              it = Info.Instructions.begin(), ie = Info.Instructions.end(); 
@@ -909,11 +977,35 @@
         (*it)->dump();
     });
 
-  // FIXME: At this point we should be able to totally order Infos, if not then
-  // we have an ambiguity which the .td file should be forced to resolve.
+  // Check for ambiguous instructions.
+  unsigned NumAmbiguous = 0;
+  for (std::vector<InstructionInfo*>::const_iterator it =
+         Info.Instructions.begin(), ie = Info.Instructions.end() - 1;
+       it != ie;) {
+    InstructionInfo &II = **it;
+    ++it;
+
+    InstructionInfo &Next = **it;
+    
+    if (!(II < Next)){
+      DEBUG_WITH_TYPE("ambiguous_instrs", {
+          errs() << "warning: ambiguous instruction match:\n";
+          II.dump();
+          errs() << "\nis incomparable with:\n";
+          Next.dump();
+          errs() << "\n\n";
+        });
+      ++NumAmbiguous;
+    }
+  }
+  if (NumAmbiguous)
+    DEBUG_WITH_TYPE("ambiguous_instrs", {
+        errs() << "warning: " << NumAmbiguous 
+               << " ambiguous instructions!\n";
+      });
 
-  // Generate the terminal actions to convert operands into an MCInst.
-  ConstructConversionFunctions(Target, Info.Instructions, OS);
+  // Generate the unified function to convert operands into an MCInst.
+  EmitConvertToMCInst(Target, Info.Instructions, OS);
 
   // Emit the enumeration for classes which participate in matching.
   EmitMatchClassEnumeration(Target, Info.Classes, OS);





More information about the llvm-commits mailing list