tblgen/AsmMatcher: Emit simple matcher for register names.
[oota-llvm.git] / utils / TableGen / IntrinsicEmitter.cpp
index 9c4338e2eb98319956860a03745681f4738ba109..f4157bb460997148ba9127ce1dce429bdca2f829 100644 (file)
@@ -22,17 +22,23 @@ using namespace llvm;
 // IntrinsicEmitter Implementation
 //===----------------------------------------------------------------------===//
 
-void IntrinsicEmitter::run(std::ostream &OS) {
+void IntrinsicEmitter::run(raw_ostream &OS) {
   EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
   
-  std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records);
+  std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
+  
+  if (TargetOnly && !Ints.empty())
+    TargetPrefix = Ints[0].TargetPrefix;
 
   // Emit the enum information.
   EmitEnumInfo(Ints, OS);
 
   // Emit the intrinsic ID -> name table.
   EmitIntrinsicToNameTable(Ints, OS);
-  
+
+  // Emit the intrinsic ID -> overload table.
+  EmitIntrinsicToOverloadTable(Ints, OS);
+
   // Emit the function name recognizer.
   EmitFnNameRecognizer(Ints, OS);
   
@@ -45,6 +51,9 @@ void IntrinsicEmitter::run(std::ostream &OS) {
   // Emit the intrinsic parameter attributes.
   EmitAttributes(Ints, OS);
 
+  // Emit intrinsic alias analysis mod/ref behavior.
+  EmitModRefBehavior(Ints, OS);
+
   // Emit a list of intrinsics with corresponding GCC builtins.
   EmitGCCBuiltinList(Ints, OS);
 
@@ -53,7 +62,7 @@ void IntrinsicEmitter::run(std::ostream &OS) {
 }
 
 void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
-                                    std::ostream &OS) {
+                                    raw_ostream &OS) {
   OS << "// Enum values for Intrinsics.h\n";
   OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
   for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
@@ -67,7 +76,7 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
 
 void IntrinsicEmitter::
 EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 
-                     std::ostream &OS) {
+                     raw_ostream &OS) {
   // Build a function name -> intrinsic name mapping.
   std::map<std::string, unsigned> IntMapping;
   for (unsigned i = 0, e = Ints.size(); i != e; ++i)
@@ -91,12 +100,12 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
     if (Ints[I->second].isOverloaded)
       OS << "    if (Len > " << I->first.size()
        << " && !memcmp(Name, \"" << I->first << ".\", "
-       << (I->first.size() + 1) << ")) return Intrinsic::"
+       << (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 Intrinsic::"
+         << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::"
          << Ints[I->second].EnumName << ";\n";
   }
   OS << "  }\n";
@@ -105,7 +114,7 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
 
 void IntrinsicEmitter::
 EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, 
-                         std::ostream &OS) {
+                         raw_ostream &OS) {
   OS << "// Intrinsic ID to name table\n";
   OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
   OS << "  // Note that entry #0 is the invalid intrinsic!\n";
@@ -114,13 +123,30 @@ EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "#endif\n\n";
 }
 
-static void EmitTypeForValueType(std::ostream &OS, MVT::SimpleValueType VT) {
+void IntrinsicEmitter::
+EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, 
+                         raw_ostream &OS) {
+  OS << "// Intrinsic ID to overload table\n";
+  OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
+  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
+  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+    OS << "  ";
+    if (Ints[i].isOverloaded)
+      OS << "true";
+    else
+      OS << "false";
+    OS << ",\n";
+  }
+  OS << "#endif\n\n";
+}
+
+static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
   if (MVT(VT).isInteger()) {
     unsigned BitWidth = MVT(VT).getSizeInBits();
     OS << "IntegerType::get(" << BitWidth << ")";
   } else if (VT == MVT::Other) {
     // MVT::OtherVT is used to mean the empty struct type here.
-    OS << "StructType::get(std::vector<const Type *>())";
+    OS << "StructType::get()";
   } else if (VT == MVT::f32) {
     OS << "Type::FloatTy";
   } else if (VT == MVT::f64) {
@@ -133,15 +159,17 @@ static void EmitTypeForValueType(std::ostream &OS, MVT::SimpleValueType VT) {
     OS << "Type::PPC_FP128Ty";
   } else if (VT == MVT::isVoid) {
     OS << "Type::VoidTy";
+  } else if (VT == MVT::Metadata) {
+    OS << "Type::MetadataTy";
   } else {
     assert(false && "Unsupported ValueType!");
   }
 }
 
-static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
+static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
                              unsigned &ArgNo);
 
-static void EmitTypeGenerate(std::ostream &OS,
+static void EmitTypeGenerate(raw_ostream &OS,
                              const std::vector<Record*> &ArgTypes,
                              unsigned &ArgNo) {
   if (ArgTypes.size() == 1) {
@@ -160,14 +188,21 @@ static void EmitTypeGenerate(std::ostream &OS,
   OS << " NULL)";
 }
 
-static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
+static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
                              unsigned &ArgNo) {
   MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
 
   if (ArgType->isSubClassOf("LLVMMatchType")) {
     unsigned Number = ArgType->getValueAsInt("Number");
     assert(Number < ArgNo && "Invalid matching number!");
-    OS << "Tys[" << Number << "]";
+    if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+      OS << "VectorType::getExtendedElementVectorType"
+         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
+    else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+      OS << "VectorType::getTruncatedElementVectorType"
+         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
+    else
+      OS << "Tys[" << Number << "]";
   } else if (VT == MVT::iAny || VT == MVT::fAny) {
     // NOTE: The ArgNo variable here is not the absolute argument number, it is
     // the index of the "arbitrary" type in the Tys array passed to the
@@ -203,7 +238,7 @@ static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
   }
 }
 
-/// RecordListComparator - Provide a determinstic comparator for lists of
+/// RecordListComparator - Provide a deterministic comparator for lists of
 /// records.
 namespace {
   typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
@@ -222,7 +257,7 @@ namespace {
           return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
       } while (++i != LHSSize);
 
-      if (i != RHSSize) return false;
+      if (i != RHSSize) return true;
 
       i = 0;
       LHSVec = &LHS.second;
@@ -242,7 +277,7 @@ namespace {
 }
 
 void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, 
-                                    std::ostream &OS) {
+                                    raw_ostream &OS) {
   OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
   OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
   OS << "  switch (ID) {\n";
@@ -280,8 +315,12 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
 
       if (ArgType->isSubClassOf("LLVMMatchType")) {
         unsigned Number = ArgType->getValueAsInt("Number");
-        assert(Number < j && "Invalid matching number!");
-        OS << "~" << Number;
+        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+          OS << "~(ExtendedElementVectorType | " << Number << ")";
+        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+          OS << "~(TruncatedElementVectorType | " << Number << ")";
+        else
+          OS << "~" << Number;
       } else {
         MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
         OS << getEnumName(VT);
@@ -298,8 +337,12 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
 
       if (ArgType->isSubClassOf("LLVMMatchType")) {
         unsigned Number = ArgType->getValueAsInt("Number");
-        assert(Number < j + RetTys.size() && "Invalid matching number!");
-        OS << "~" << Number;
+        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+          OS << "~(ExtendedElementVectorType | " << Number << ")";
+        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+          OS << "~(TruncatedElementVectorType | " << Number << ")";
+        else
+          OS << "~" << Number;
       } else {
         MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
         OS << getEnumName(VT);
@@ -317,7 +360,7 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
 }
 
 void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 
-                                     std::ostream &OS) {
+                                     raw_ostream &OS) {
   OS << "// Code for generating Intrinsic function declarations.\n";
   OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
   OS << "  switch (id) {\n";
@@ -334,11 +377,13 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
                              Ints[i].IS.ParamTypeDefs)].push_back(i);
 
   // Loop through the array, emitting one generator for each batch.
+  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
+  
   for (MapTy::iterator I = UniqueArgInfos.begin(),
        E = UniqueArgInfos.end(); I != E; ++I) {
     for (unsigned i = 0, e = I->second.size(); i != e; ++i)
-      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
-         << Ints[I->second[i]].Name << "\n";
+      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName 
+         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
     
     const RecPair &ArgTypes = I->first;
     const std::vector<Record*> &RetTys = ArgTypes.first;
@@ -370,17 +415,29 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "#endif\n\n";
 }
 
+/// EmitAttributes - This emits the Intrinsic::getAttributes method.
 void IntrinsicEmitter::
-EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
+EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
   OS << "// Add parameter attributes that are not common to all intrinsics.\n";
   OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
+  if (TargetOnly)
+    OS << "static AttrListPtr getAttributes(" << TargetPrefix 
+       << "Intrinsic::ID id) {";
+  else
+    OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
+  OS << "  // No intrinsic can throw exceptions.\n";
+  OS << "  Attributes Attr = Attribute::NoUnwind;\n";
   OS << "  switch (id) {\n";
   OS << "  default: break;\n";
+  unsigned MaxArgAttrs = 0;
   for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+    MaxArgAttrs =
+      std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size()));
     switch (Ints[i].ModRef) {
     default: break;
     case CodeGenIntrinsic::NoMem:
-      OS << "  case Intrinsic::" << Ints[i].EnumName << ":\n";
+      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 
+         << ":\n";
       break;
     }
   }
@@ -391,18 +448,95 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
     default: break;
     case CodeGenIntrinsic::ReadArgMem:
     case CodeGenIntrinsic::ReadMem:
-      OS << "  case Intrinsic::" << Ints[i].EnumName << ":\n";
+      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 
+         << ":\n";
       break;
     }
   }
   OS << "    Attr |= Attribute::ReadOnly; // These do not write memory.\n";
   OS << "    break;\n";
   OS << "  }\n";
-  OS << "#endif\n\n";
+  OS << "  AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n";
+  OS << "  unsigned NumAttrs = 0;\n";
+  OS << "  switch (id) {\n";
+  OS << "  default: break;\n";
+  
+  // Add argument attributes for any intrinsics that have them.
+  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+    if (Ints[i].ArgumentAttributes.empty()) continue;
+    
+    OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 
+       << ":\n";
+
+    std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
+      Ints[i].ArgumentAttributes;
+    // Sort by argument index.
+    std::sort(ArgAttrs.begin(), ArgAttrs.end());
+
+    unsigned NumArgsWithAttrs = 0;
+
+    while (!ArgAttrs.empty()) {
+      unsigned ArgNo = ArgAttrs[0].first;
+      
+      OS << "    AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get("
+         << ArgNo+1 << ", 0";
+
+      while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) {
+        switch (ArgAttrs[0].second) {
+        default: assert(0 && "Unknown arg attribute");
+        case CodeGenIntrinsic::NoCapture:
+          OS << "|Attribute::NoCapture";
+          break;
+        }
+        ArgAttrs.erase(ArgAttrs.begin());
+      }
+      OS << ");\n";
+    }
+    
+    OS << "    NumAttrs = " << NumArgsWithAttrs << ";\n";
+    OS << "    break;\n";
+  }
+  
+  OS << "  }\n";
+  OS << "  AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n";
+  OS << "  return AttrListPtr::get(AWI, NumAttrs+1);\n";
+  OS << "}\n";
+  OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
 }
 
+/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
 void IntrinsicEmitter::
-EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){
+EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
+  OS << "// Determine intrinsic alias analysis mod/ref behavior.\n";
+  OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n";
+  OS << "switch (id) {\n";
+  OS << "default:\n    return UnknownModRefBehavior;\n";
+  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+    if (Ints[i].ModRef == CodeGenIntrinsic::WriteMem)
+      continue;
+    OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+      << ":\n";
+    switch (Ints[i].ModRef) {
+    default:
+      assert(false && "Unknown Mod/Ref type!");
+    case CodeGenIntrinsic::NoMem:
+      OS << "  return DoesNotAccessMemory;\n";
+      break;
+    case CodeGenIntrinsic::ReadArgMem:
+    case CodeGenIntrinsic::ReadMem:
+      OS << "  return OnlyReadsMemory;\n";
+      break;
+    case CodeGenIntrinsic::WriteArgMem:
+      OS << "  return AccessesArguments;\n";
+      break;
+    }
+  }
+  OS << "}\n";
+  OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
+}
+
+void IntrinsicEmitter::
+EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
   OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n";
   OS << "#ifdef GET_GCC_BUILTIN_NAME\n";
   OS << "  switch (F->getIntrinsicID()) {\n";
@@ -427,7 +561,7 @@ EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){
 typedef std::map<std::string, std::string>::const_iterator StrMapIterator;
 static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
                                    unsigned CharStart, unsigned Indent,
-                                   std::ostream &OS) {
+                                   std::string TargetPrefix, raw_ostream &OS) {
   if (Start == End) return; // empty range.
   
   // Determine what, if anything, is the same about all these strings.
@@ -454,7 +588,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
       OS << CommonString.size() - CharStart << "))\n";
       ++Indent;
     }
-    OS << std::string(Indent*2, ' ') << "IntrinsicID = Intrinsic::";
+    OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix
+       << "Intrinsic::";
     OS << Start->second << ";\n";
     return;
   }
@@ -467,7 +602,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
     OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
     OS << CommonString.size()-CharStart << ")) {\n";
     
-    EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, OS);
+    EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, 
+                           TargetPrefix, OS);
     OS << std::string(Indent*2, ' ') << "}\n";
     return;
   }
@@ -488,7 +624,7 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
     for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
          ++NextChar)
       /*empty*/;
-    EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, OS);
+    EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS);
     OS << std::string(Indent*2, ' ') << "  break;\n";
     I = NextChar;
   }
@@ -498,7 +634,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
 /// 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,
-                               std::ostream &OS) {
+                               const std::string &TargetPrefix,
+                               raw_ostream &OS) {
   // Rearrange the builtins by length.
   std::vector<std::map<std::string, std::string> > BuiltinsByLen;
   BuiltinsByLen.reserve(100);
@@ -516,7 +653,7 @@ static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
     if (BuiltinsByLen[i].empty()) continue;
     OS << "    case " << i << ":\n";
     EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
-                           0, 3, OS);
+                           0, 3, TargetPrefix, OS);
     OS << "      break;\n";
   }
   OS << "    }\n";
@@ -525,7 +662,7 @@ static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
         
 void IntrinsicEmitter::
 EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, 
-                             std::ostream &OS) {
+                             raw_ostream &OS) {
   typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
   BIMTy BuiltinMap;
   for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
@@ -545,7 +682,22 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
   OS << "// in as TargetPrefix.  The result is assigned to 'IntrinsicID'.\n";
   OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
-  OS << "  IntrinsicID = Intrinsic::not_intrinsic;\n";
+  
+  if (TargetOnly) {
+    OS << "static " << TargetPrefix << "Intrinsic::ID "
+       << "getIntrinsicForGCCBuiltin(const char "
+       << "*TargetPrefix, const char *BuiltinName) {\n";
+    OS << "  " << TargetPrefix << "Intrinsic::ID IntrinsicID = ";
+  } else {
+    OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
+       << "*TargetPrefix, const char *BuiltinName) {\n";
+    OS << "  Intrinsic::ID IntrinsicID = ";
+  }
+  
+  if (TargetOnly)
+    OS << "(" << TargetPrefix<< "Intrinsic::ID)";
+
+  OS << "Intrinsic::not_intrinsic;\n";
   
   // Note: this could emit significantly better code if we cared.
   for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
@@ -557,8 +709,10 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
     OS << "{\n";
 
     // Emit the comparisons for this target prefix.
-    EmitTargetBuiltins(I->second, OS);
+    EmitTargetBuiltins(I->second, TargetPrefix, OS);
     OS << "  }\n";
   }
+  OS << "  return IntrinsicID;\n";
+  OS << "}\n";
   OS << "#endif\n\n";
 }