diff options
Diffstat (limited to 'utils/TableGen/IntrinsicEmitter.cpp')
| -rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 204 | 
1 files changed, 66 insertions, 138 deletions
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index ba30d97eaa35..08f67284a279 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -14,6 +14,7 @@  #include "CodeGenTarget.h"  #include "IntrinsicEmitter.h"  #include "Record.h" +#include "StringMatcher.h"  #include "llvm/ADT/StringExtras.h"  #include <algorithm>  using namespace llvm; @@ -67,16 +68,19 @@ void IntrinsicEmitter::run(raw_ostream &OS) {  void IntrinsicEmitter::EmitPrefix(raw_ostream &OS) {    OS << "// VisualStudio defines setjmp as _setjmp\n" -        "#if defined(_MSC_VER) && defined(setjmp)\n" -        "#define setjmp_undefined_for_visual_studio\n" -        "#undef setjmp\n" +        "#if defined(_MSC_VER) && defined(setjmp) && \\\n" +        "                         !defined(setjmp_undefined_for_msvc)\n" +        "#  pragma push_macro(\"setjmp\")\n" +        "#  undef setjmp\n" +        "#  define setjmp_undefined_for_msvc\n"          "#endif\n\n";  }  void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) { -  OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio)\n" +  OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n"          "// let's return it to _setjmp state\n" -        "#define setjmp _setjmp\n" +        "#  pragma pop_macro(\"setjmp\")\n" +        "#  undef setjmp_undefined_for_msvc\n"          "#endif\n\n";  } @@ -96,37 +100,48 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,  void IntrinsicEmitter::  EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,                        raw_ostream &OS) { -  // Build a function name -> intrinsic name mapping. -  std::map<std::string, unsigned> IntMapping; +  // Build a 'first character of function name' -> intrinsic # mapping. +  std::map<char, std::vector<unsigned> > IntMapping;    for (unsigned i = 0, e = Ints.size(); i != e; ++i) -    IntMapping[Ints[i].Name] = i; -     +    IntMapping[Ints[i].Name[5]].push_back(i); +      OS << "// Function name -> enum value recognizer code.\n";    OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; -  OS << "  switch (Name[5]) {\n"; -  OS << "  default:\n"; -  // Emit the intrinsics in sorted order. -  char LastChar = 0; -  for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(), +  OS << "  StringRef NameR(Name+6, Len-6);   // Skip over 'llvm.'\n"; +  OS << "  switch (Name[5]) {                  // Dispatch on first letter.\n"; +  OS << "  default: break;\n"; +  // 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) { -    if (I->first[5] != LastChar) { -      LastChar = I->first[5]; -      OS << "    break;\n"; -      OS << "  case '" << LastChar << "':\n"; +    OS << "  case '" << I->first << "':\n"; +    std::vector<unsigned> &IntList = I->second; + +    // Emit all the overloaded intrinsics first, build a table of the +    // non-overloaded ones. +    std::vector<StringMatcher::StringPair> MatchTable; +     +    for (unsigned i = 0, e = IntList.size(); i != e; ++i) { +      unsigned IntNo = IntList[i]; +      std::string Result = "return " + TargetPrefix + "Intrinsic::" + +        Ints[IntNo].EnumName + ";"; + +      if (!Ints[IntNo].isOverloaded) { +        MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result)); +        continue; +      } + +      // For overloaded intrinsics, only the prefix needs to match +      std::string TheStr = Ints[IntNo].Name.substr(6); +      TheStr += '.';  // Require "bswap." instead of bswap. +      OS << "    if (NameR.startswith(\"" << TheStr << "\")) " +         << Result << '\n';      } -    // For overloaded intrinsics, only the prefix needs to match -    if (Ints[I->second].isOverloaded) -      OS << "    if (Len > " << I->first.size() -       << " && !memcmp(Name, \"" << I->first << ".\", " -       << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::" -       << Ints[I->second].EnumName << ";\n"; -    else  -      OS << "    if (Len == " << I->first.size() -         << " && !memcmp(Name, \"" << I->first << "\", " -         << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::" -         << Ints[I->second].EnumName << ";\n"; +    // Emit the matcher logic for the fixed length strings. +    StringMatcher("NameR", MatchTable, OS).Emit(1); +    OS << "    break;  // end of '" << I->first << "' case.\n";    } +      OS << "  }\n";    OS << "#endif\n\n";  } @@ -180,6 +195,8 @@ static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {      OS << "Type::getVoidTy(Context)";    } else if (VT == MVT::Metadata) {      OS << "Type::getMetadataTy(Context)"; +  } else if (VT == MVT::x86mmx) { +    OS << "Type::getX86_MMXTy(Context)";    } else {      assert(false && "Unsupported ValueType!");    } @@ -556,11 +573,13 @@ EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){        OS << "  return DoesNotAccessMemory;\n";        break;      case CodeGenIntrinsic::ReadArgMem: +      OS << "  return OnlyReadsArgumentPointees;\n"; +      break;      case CodeGenIntrinsic::ReadMem:        OS << "  return OnlyReadsMemory;\n";        break;      case CodeGenIntrinsic::ReadWriteArgMem: -      OS << "  return AccessesArguments;\n"; +      OS << "  return OnlyAccessesArgumentPointees;\n";        break;      }    } @@ -584,112 +603,22 @@ EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){    OS << "#endif\n\n";  } -/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified -/// sorted range of builtin names is equal to the current builtin.  This breaks -/// it down into a simple tree. -/// -/// At this point, we know that all the builtins in the range have the same name -/// for the first 'CharStart' characters.  Only the end of the name needs to be -/// discriminated. -typedef std::map<std::string, std::string>::const_iterator StrMapIterator; -static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, -                                   unsigned CharStart, unsigned Indent, -                                   std::string TargetPrefix, raw_ostream &OS) { -  if (Start == End) return; // empty range. -   -  // Determine what, if anything, is the same about all these strings. -  std::string CommonString = Start->first; -  unsigned NumInRange = 0; -  for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) { -    // Find the first character that doesn't match. -    const std::string &ThisStr = I->first; -    unsigned NonMatchChar = CharStart; -    while (NonMatchChar < CommonString.size() &&  -           NonMatchChar < ThisStr.size() && -           CommonString[NonMatchChar] == ThisStr[NonMatchChar]) -      ++NonMatchChar; -    // Truncate off pieces that don't match. -    CommonString.resize(NonMatchChar); -  } -   -  // Just compare the rest of the string. -  if (NumInRange == 1) { -    if (CharStart != CommonString.size()) { -      OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; -      if (CharStart) OS << "+" << CharStart; -      OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; -      OS << CommonString.size() - CharStart << "))\n"; -      ++Indent; -    } -    OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix -       << "Intrinsic::"; -    OS << Start->second << ";\n"; -    return; -  } - -  // At this point, we potentially have a common prefix for these builtins, emit -  // a check for this common prefix. -  if (CommonString.size() != CharStart) { -    OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; -    if (CharStart) OS << "+" << CharStart; -    OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; -    OS << CommonString.size()-CharStart << ")) {\n"; -     -    EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1,  -                           TargetPrefix, OS); -    OS << std::string(Indent*2, ' ') << "}\n"; -    return; -  } -   -  // Output a switch on the character that differs across the set. -  OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart -      << "]) {"; -  if (CharStart) -    OS << "  // \"" << std::string(Start->first.begin(),  -                                   Start->first.begin()+CharStart) << "\""; -  OS << "\n"; -   -  for (StrMapIterator I = Start; I != End; ) { -    char ThisChar = I->first[CharStart]; -    OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n"; -    // Figure out the range that has this common character. -    StrMapIterator NextChar = I; -    for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar; -         ++NextChar) -      /*empty*/; -    EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS); -    OS << std::string(Indent*2, ' ') << "  break;\n"; -    I = NextChar; -  } -  OS << std::string(Indent*2, ' ') << "}\n"; -} -  /// EmitTargetBuiltins - All of the builtins in the specified map are for the  /// same target, and we already checked it.  static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,                                 const std::string &TargetPrefix,                                 raw_ostream &OS) { -  // Rearrange the builtins by length. -  std::vector<std::map<std::string, std::string> > BuiltinsByLen; -  BuiltinsByLen.reserve(100); -  for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) { -    if (I->first.size() >= BuiltinsByLen.size()) -      BuiltinsByLen.resize(I->first.size()+1); -    BuiltinsByLen[I->first.size()].insert(*I); -  } +  std::vector<StringMatcher::StringPair> Results; -  // Now that we have all the builtins by their length, emit a switch stmt. -  OS << "    switch (strlen(BuiltinName)) {\n"; -  OS << "    default: break;\n"; -  for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) { -    if (BuiltinsByLen[i].empty()) continue; -    OS << "    case " << i << ":\n"; -    EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(), -                           0, 3, TargetPrefix, OS); -    OS << "      break;\n"; +  for (std::map<std::string, std::string>::const_iterator I = BIM.begin(), +       E = BIM.end(); I != E; ++I) { +    std::string ResultCode = +    "return " + TargetPrefix + "Intrinsic::" + I->second + ";"; +    Results.push_back(StringMatcher::StringPair(I->first, ResultCode));    } -  OS << "    }\n"; + +  StringMatcher("BuiltinName", Results, OS).Emit();  } @@ -719,24 +648,20 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,    if (TargetOnly) {      OS << "static " << TargetPrefix << "Intrinsic::ID "         << "getIntrinsicForGCCBuiltin(const char " -       << "*TargetPrefix, const char *BuiltinName) {\n"; -    OS << "  " << TargetPrefix << "Intrinsic::ID IntrinsicID = "; +       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";    } else {      OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " -       << "*TargetPrefix, const char *BuiltinName) {\n"; -    OS << "  Intrinsic::ID IntrinsicID = "; +       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";    } -  if (TargetOnly) -    OS << "(" << TargetPrefix<< "Intrinsic::ID)"; - -  OS << "Intrinsic::not_intrinsic;\n"; +  OS << "  StringRef BuiltinName(BuiltinNameStr);\n"; +  OS << "  StringRef TargetPrefix(TargetPrefixStr);\n\n";    // Note: this could emit significantly better code if we cared.    for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){      OS << "  ";      if (!I->first.empty()) -      OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) "; +      OS << "if (TargetPrefix == \"" << I->first << "\") ";      else        OS << "/* Target Independent Builtins */ ";      OS << "{\n"; @@ -745,7 +670,10 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,      EmitTargetBuiltins(I->second, TargetPrefix, OS);      OS << "  }\n";    } -  OS << "  return IntrinsicID;\n"; +  OS << "  return "; +  if (!TargetPrefix.empty()) +    OS << "(" << TargetPrefix << "Intrinsic::ID)"; +  OS << "Intrinsic::not_intrinsic;\n";    OS << "}\n";    OS << "#endif\n\n";  }  | 
