Extend AsmMatcher token literal matching to allow aliasing.
authorJim Grosbach <grosbach@apple.com>
Tue, 6 Dec 2011 23:43:54 +0000 (23:43 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 6 Dec 2011 23:43:54 +0000 (23:43 +0000)
For example, ARM allows:
    vmov.u32 s4, #0  -> vmov.i32, #0
'u32' is a more specific designator for the 32-bit integer type specifier
and is legal for any instruction which accepts 'i32' as a datatype suffix.

We want to say,
    def : TokenAlias<".u32", ".i32">;

This works by marking the match class of 'From' as a subclass of the
match class of 'To'.

rdar://10435076

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

include/llvm/Target/Target.td
utils/TableGen/AsmMatcherEmitter.cpp

index 26e59e452f57e54c3917be195f249f558ff7d6d1..c9b6a8ec419cbd023a5db47e8c9a9e7caf9544cd 100644 (file)
@@ -738,7 +738,20 @@ class AssemblerPredicate<string cond> {
   string AssemblerCondString = cond;
 }
 
-
+/// TokenAlias - This class allows targets to define assembler token
+/// operand aliases. That is, a token literal operand which is equivalent
+/// to another, canonical, token literal. For example, ARM allows:
+///   vmov.u32 s4, #0  -> vmov.i32, #0
+/// 'u32' is a more specific designator for the 32-bit integer type specifier
+/// and is legal for any instruction which accepts 'i32' as a datatype suffix.
+///   def : TokenAlias<".u32", ".i32">;
+///
+/// This works by marking the match class of 'From' as a subclass of the
+/// match class of 'To'.
+class TokenAlias<string From, string To> {
+  string FromToken = From;
+  string ToToken = To;
+}
 
 /// MnemonicAlias - This class allows targets to define assembler mnemonic
 /// aliases.  This should be used when all forms of one mnemonic are accepted
index e83fa0de9daad591a2935262c9ac6a7678639b61..5ef0db905ccfcffde2c477ef063435992d5e5a73 100644 (file)
@@ -252,11 +252,6 @@ public:
     switch (Kind) {
     case Invalid:
       assert(0 && "Invalid kind!");
-    case Token:
-      // Tokens are comparable by value.
-      //
-      // FIXME: Compare by enum value.
-      return ValueName < RHS.ValueName;
 
     default:
       // This class precedes the RHS if it is a proper subset of the RHS.
@@ -1304,6 +1299,17 @@ void AsmMatcherInfo::BuildInfo() {
       II->BuildAliasResultOperands();
   }
 
+  // Process token alias definitions and set up the associated superclass
+  // information.
+  std::vector<Record*> AllTokenAliases =
+    Records.getAllDerivedDefinitions("TokenAlias");
+  for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) {
+    Record *Rec = AllTokenAliases[i];
+    ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken"));
+    ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken"));
+    FromClass->SuperClasses.push_back(ToClass);
+  }
+
   // Reorder classes so that classes precede super classes.
   std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
 }
@@ -1676,7 +1682,8 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info,
 
   // Check for Token operands first.
   OS << "  if (Operand.isToken())\n";
-  OS << "    return matchTokenString(Operand.getToken()) == Kind;\n\n";
+  OS << "    return isSubclass(matchTokenString(Operand.getToken()), Kind);"
+     << "\n\n";
 
   // Check for register operands, including sub-classes.
   OS << "  if (Operand.isReg()) {\n";
@@ -1729,32 +1736,30 @@ static void EmitIsSubclass(CodeGenTarget &Target,
          ie = Infos.end(); it != ie; ++it) {
     ClassInfo &A = **it;
 
-    if (A.Kind != ClassInfo::Token) {
-      std::vector<StringRef> SuperClasses;
-      for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
-             ie = Infos.end(); it != ie; ++it) {
-        ClassInfo &B = **it;
-
-        if (&A != &B && A.isSubsetOf(B))
-          SuperClasses.push_back(B.Name);
-      }
+    std::vector<StringRef> SuperClasses;
+    for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+         ie = Infos.end(); it != ie; ++it) {
+      ClassInfo &B = **it;
 
-      if (SuperClasses.empty())
-        continue;
+      if (&A != &B && A.isSubsetOf(B))
+        SuperClasses.push_back(B.Name);
+    }
 
-      OS << "\n  case " << A.Name << ":\n";
+    if (SuperClasses.empty())
+      continue;
 
-      if (SuperClasses.size() == 1) {
-        OS << "    return B == " << SuperClasses.back() << ";\n";
-        continue;
-      }
+    OS << "\n  case " << A.Name << ":\n";
 
-      OS << "    switch (B) {\n";
-      OS << "    default: return false;\n";
-      for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
-        OS << "    case " << SuperClasses[i] << ": return true;\n";
-      OS << "    }\n";
+    if (SuperClasses.size() == 1) {
+      OS << "    return B == " << SuperClasses.back() << ";\n";
+      continue;
     }
+
+    OS << "    switch (B) {\n";
+    OS << "    default: return false;\n";
+    for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+      OS << "    case " << SuperClasses[i] << ": return true;\n";
+    OS << "    }\n";
   }
   OS << "  }\n";
   OS << "}\n\n";