Fix a bug in TableGen where the intrinsic function name recognizer could mis-identify names if one was a prefix substring of the other

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.

llvm-svn: 187119
This commit is contained in:
Justin Holewinski 2013-07-25 12:32:00 +00:00
parent 516d7971b3
commit b3d630ca21
2 changed files with 53 additions and 0 deletions

View File

@ -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]>;

View 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;