Fix a bug in TableGen where the intrinsic function name recognizer could mis-identify...
authorJustin Holewinski <jholewinski@nvidia.com>
Thu, 25 Jul 2013 12:32:00 +0000 (12:32 +0000)
committerJustin Holewinski <jholewinski@nvidia.com>
Thu, 25 Jul 2013 12:32:00 +0000 (12:32 +0000)
For two intrinsics 'llvm.nvvm.texsurf.handle' and 'llvm.nvvm.texsurf.handle.internal',
TableGen was emitting matching code like:

  if (Name.startswith("llvm.nvvm.texsurf.handle")) ...
  if (Name.startswith("llvm.nvvm.texsurf.handle.internal")) ...

We can never match "llvm.nvvm.texsurf.handle.internal" here because it will
always be erroneously matched by the first condition.

The fix is to sort the intrinsic names and emit them in reverse order.

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

test/TableGen/intrinsic-order.td [new file with mode: 0644]
utils/TableGen/IntrinsicEmitter.cpp

diff --git a/test/TableGen/intrinsic-order.td b/test/TableGen/intrinsic-order.td
new file mode 100644 (file)
index 0000000..5eadf60
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: llvm-tblgen -gen-intrinsic %s | FileCheck %s
+
+class IntrinsicProperty;
+
+class ValueType<int size, int value> {
+  string Namespace = "MVT";
+  int Size = size;
+  int Value = value;
+}
+
+class LLVMType<ValueType vt> {
+  ValueType VT = vt;
+}
+
+class Intrinsic<string name, list<LLVMType> param_types = []> {
+  string LLVMName = name;
+  bit isTarget = 0;
+  string TargetPrefix = "";
+  list<LLVMType> RetTypes = [];
+  list<LLVMType> ParamTypes = param_types;
+  list<IntrinsicProperty> Properties = [];
+}
+
+def iAny : ValueType<0, 254>;
+def llvm_anyint_ty : LLVMType<iAny>;
+
+
+// Make sure an intrinsic name that is a prefix of another is checked after the
+// other.
+
+// CHECK: if (NameR.startswith("oo.bar.")) return Intrinsic::foo_bar;
+// CHECK: if (NameR.startswith("oo.")) return Intrinsic::foo;
+
+def int_foo : Intrinsic<"llvm.foo", [llvm_anyint_ty]>;
+def int_foo_bar : Intrinsic<"llvm.foo.bar", [llvm_anyint_ty]>;
index c83797c25df3fd93c0a982f78649c94a1a1a9110..c508795cc88109b9e80ef36faf5dfc3661578d50 100644 (file)
@@ -131,6 +131,20 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "#endif\n\n";
 }
 
+struct IntrinsicNameSorter {
+  IntrinsicNameSorter(const std::vector<CodeGenIntrinsic> &I)
+  : Ints(I) {}
+
+  // Sort in reverse order of intrinsic name so "abc.def" appears after
+  // "abd.def.ghi" in the overridden name matcher
+  bool operator()(unsigned i, unsigned j) {
+    return Ints[i].Name > Ints[j].Name;
+  }
+
+private:
+  const std::vector<CodeGenIntrinsic> &Ints;
+};
+
 void IntrinsicEmitter::
 EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 
                      raw_ostream &OS) {
@@ -144,12 +158,16 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "  StringRef NameR(Name+6, Len-6);   // Skip over 'llvm.'\n";
   OS << "  switch (Name[5]) {                  // Dispatch on first letter.\n";
   OS << "  default: break;\n";
+  IntrinsicNameSorter Sorter(Ints);
   // Emit the intrinsic matching stuff by first letter.
   for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(),
        E = IntMapping.end(); I != E; ++I) {
     OS << "  case '" << I->first << "':\n";
     std::vector<unsigned> &IntList = I->second;
 
+    // Sort intrinsics in reverse order of their names
+    std::sort(IntList.begin(), IntList.end(), Sorter);
+
     // Emit all the overloaded intrinsics first, build a table of the
     // non-overloaded ones.
     std::vector<StringMatcher::StringPair> MatchTable;