Modify the intrinsics pattern to separate out the "return" types from the
"parameter" types. An intrinsic can now return a multiple return values like
this:

  def add_with_overflow : Intrinsic<[llvm_i32_ty, llvm_i1_ty],
                                    [LLVMMatchType<0>, LLVMMatchType<0>]>;



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59237 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index e987c2b..859a8cc 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -471,7 +471,8 @@
   }
 
   if (getExtTypeNum(0) == MVT::iPTR || getExtTypeNum(0) == MVT::iPTRAny) {
-    if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny || ExtVTs[0] == EMVT::isInt)
+    if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny ||
+        ExtVTs[0] == EMVT::isInt)
       return false;
     if (EMVT::isExtIntegerInVTs(ExtVTs)) {
       std::vector<unsigned char> FVTs = FilterEVTs(ExtVTs, isInteger);
@@ -885,18 +886,22 @@
     bool MadeChange = false;
 
     // Apply the result type to the node.
-    MadeChange = UpdateNodeType(Int->ArgVTs[0], TP);
+    unsigned NumRetVTs = Int->IS.RetVTs.size();
+    unsigned NumParamVTs = Int->IS.ParamVTs.size();
 
-    if (getNumChildren() != Int->ArgVTs.size())
+    for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
+      MadeChange |= UpdateNodeType(Int->IS.RetVTs[i], TP);
+
+    if (getNumChildren() != NumParamVTs + NumRetVTs)
       TP.error("Intrinsic '" + Int->Name + "' expects " +
-               utostr(Int->ArgVTs.size()-1) + " operands, not " +
-               utostr(getNumChildren()-1) + " operands!");
+               utostr(NumParamVTs + NumRetVTs - 1) + " operands, not " +
+               utostr(getNumChildren() - 1) + " operands!");
 
     // Apply type info to the intrinsic ID.
     MadeChange |= getChild(0)->UpdateNodeType(MVT::iPTR, TP);
     
-    for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
-      MVT::SimpleValueType OpVT = Int->ArgVTs[i];
+    for (unsigned i = NumRetVTs, e = getNumChildren(); i != e; ++i) {
+      MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i - NumRetVTs];
       MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP);
       MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
     }
@@ -1232,7 +1237,7 @@
 
     // If this intrinsic returns void, it must have side-effects and thus a
     // chain.
-    if (Int.ArgVTs[0] == MVT::isVoid) {
+    if (Int.IS.RetVTs[0] == MVT::isVoid) {
       Operator = getDAGPatterns().get_intrinsic_void_sdnode();
     } else if (Int.ModRef != CodeGenIntrinsic::NoMem) {
       // Has side-effects, requires chain.
diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h
index 4de9386..1170da0 100644
--- a/utils/TableGen/CodeGenIntrinsics.h
+++ b/utils/TableGen/CodeGenIntrinsics.h
@@ -30,16 +30,34 @@
     std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "".
     std::string TargetPrefix;  // Target prefix, e.g. "ppc" for t-s intrinsics.
 
-    /// ArgVTs - The MVT::SimpleValueType for each argument type.  Note that
-    /// this list is only populated when in the context of a target .td file.
-    /// When building Intrinsics.td, this isn't available, because we don't know
-    /// the target pointer size.
-    std::vector<MVT::SimpleValueType> ArgVTs;
+    /// IntrinsicSignature - This structure holds the return values and
+    /// parameter values of an intrinsic. If the number of return values is > 1,
+    /// then the intrinsic implicitly returns a first-class aggregate. The
+    /// numbering of the types starts at 0 with the first return value and
+    /// continues from there throug the parameter list. This is useful for
+    /// "matching" types.
+    struct IntrinsicSignature {
+      /// RetVTs - The MVT::SimpleValueType for each return type. Note that this
+      /// list is only populated when in the context of a target .td file. When
+      /// building Intrinsics.td, this isn't available, because we don't know
+      /// the target pointer size.
+      std::vector<MVT::SimpleValueType> RetVTs;
 
-    /// ArgTypeDefs - The records for each argument type.
-    ///
-    std::vector<Record*> ArgTypeDefs;
-    
+      /// RetTypeDefs - The records for each return type.
+      std::vector<Record*> RetTypeDefs;
+
+      /// ParamVTs - The MVT::SimpleValueType for each parameter type. Note that
+      /// this list is only populated when in the context of a target .td file.
+      /// When building Intrinsics.td, this isn't available, because we don't
+      /// know the target pointer size.
+      std::vector<MVT::SimpleValueType> ParamVTs;
+
+      /// ParamTypeDefs - The records for each parameter type.
+      std::vector<Record*> ParamTypeDefs;
+    };
+
+    IntrinsicSignature IS;
+
     // Memory mod/ref behavior of this intrinsic.
     enum {
       NoMem, ReadArgMem, ReadMem, WriteArgMem, WriteMem
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 4e7a10c..2ff1b19 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -438,25 +438,27 @@
   isCommutative = false;
   
   if (DefName.size() <= 4 || 
-      std::string(DefName.begin(), DefName.begin()+4) != "int_")
+      std::string(DefName.begin(), DefName.begin() + 4) != "int_")
     throw "Intrinsic '" + DefName + "' does not start with 'int_'!";
+
   EnumName = std::string(DefName.begin()+4, DefName.end());
+
   if (R->getValue("GCCBuiltinName"))  // Ignore a missing GCCBuiltinName field.
     GCCBuiltinName = R->getValueAsString("GCCBuiltinName");
-  TargetPrefix   = R->getValueAsString("TargetPrefix");
+
+  TargetPrefix = R->getValueAsString("TargetPrefix");
   Name = R->getValueAsString("LLVMName");
+
   if (Name == "") {
     // If an explicit name isn't specified, derive one from the DefName.
     Name = "llvm.";
+
     for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
-      if (EnumName[i] == '_')
-        Name += '.';
-      else
-        Name += EnumName[i];
+      Name += (EnumName[i] == '_') ? '.' : EnumName[i];
   } else {
     // Verify it starts with "llvm.".
     if (Name.size() <= 5 || 
-        std::string(Name.begin(), Name.begin()+5) != "llvm.")
+        std::string(Name.begin(), Name.begin() + 5) != "llvm.")
       throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!";
   }
   
@@ -464,26 +466,37 @@
   // "llvm.<targetprefix>.".
   if (!TargetPrefix.empty()) {
     if (Name.size() < 6+TargetPrefix.size() ||
-        std::string(Name.begin()+5, Name.begin()+6+TargetPrefix.size()) 
-        != (TargetPrefix+"."))
-      throw "Intrinsic '" + DefName + "' does not start with 'llvm." + 
+        std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
+        != (TargetPrefix + "."))
+      throw "Intrinsic '" + DefName + "' does not start with 'llvm." +
         TargetPrefix + ".'!";
   }
   
-  // Parse the list of argument types.
-  ListInit *TypeList = R->getValueAsListInit("Types");
+  // Parse the list of return types.
+  ListInit *TypeList = R->getValueAsListInit("RetTypes");
   for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
     Record *TyEl = TypeList->getElementAsRecord(i);
     assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
     MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
     isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny;
-    ArgVTs.push_back(VT);
-    ArgTypeDefs.push_back(TyEl);
+    IS.RetVTs.push_back(VT);
+    IS.RetTypeDefs.push_back(TyEl);
   }
-  if (ArgVTs.size() == 0)
+
+  if (IS.RetVTs.size() == 0)
     throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!";
 
-  
+  // Parse the list of parameter types.
+  TypeList = R->getValueAsListInit("ParamTypes");
+  for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
+    Record *TyEl = TypeList->getElementAsRecord(i);
+    assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
+    MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
+    isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny;
+    IS.ParamVTs.push_back(VT);
+    IS.ParamTypeDefs.push_back(TyEl);
+  }
+
   // Parse the intrinsic properties.
   ListInit *PropList = R->getValueAsListInit("Properties");
   for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) {
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index ade1c8c..9247a85 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -138,7 +138,27 @@
   }
 }
 
-static void EmitTypeGenerate(std::ostream &OS, Record *ArgType, 
+static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
+                             unsigned &ArgNo);
+
+static void EmitTypeGenerate(std::ostream &OS,
+                             const std::vector<Record*> &ArgTypes,
+                             unsigned &ArgNo) {
+  if (ArgTypes.size() == 1) {
+    EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
+    return;
+  }
+
+  OS << "StructType::get(";
+
+  for (std::vector<Record*>::const_iterator
+         I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I)
+    EmitTypeGenerate(OS, *I, ArgNo);
+
+  OS << ", NULL)";
+}
+
+static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
                              unsigned &ArgNo) {
   MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
 
@@ -184,17 +204,37 @@
 /// RecordListComparator - Provide a determinstic comparator for lists of
 /// records.
 namespace {
+  typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
   struct RecordListComparator {
-    bool operator()(const std::vector<Record*> &LHS,
-                    const std::vector<Record*> &RHS) const {
+    bool operator()(const RecPair &LHS,
+                    const RecPair &RHS) const {
       unsigned i = 0;
+      const std::vector<Record*> *LHSVec = &LHS.first;
+      const std::vector<Record*> *RHSVec = &RHS.first;
+      unsigned RHSSize = RHSVec->size();
+      unsigned LHSSize = LHSVec->size();
+
       do {
-        if (i == RHS.size()) return false;  // RHS is shorter than LHS.
-        if (LHS[i] != RHS[i])
-          return LHS[i]->getName() < RHS[i]->getName();
-      } while (++i != LHS.size());
-      
-      return i != RHS.size();
+        if (i == RHSSize) return false;  // RHS is shorter than LHS.
+        if ((*LHSVec)[i] != (*RHSVec)[i])
+          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
+      } while (++i != LHSSize);
+
+      if (i != RHSSize) return false;
+
+      i = 0;
+      LHSVec = &LHS.second;
+      RHSVec = &RHS.second;
+      RHSSize = RHSVec->size();
+      LHSSize = LHSVec->size();
+
+      for (i = 0; i != LHSSize; ++i) {
+        if (i == RHSSize) return false;  // RHS is shorter than LHS.
+        if ((*LHSVec)[i] != (*RHSVec)[i])
+          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
+      }
+
+      return i != RHSSize;
     }
   };
 }
@@ -209,26 +249,33 @@
   // This checking can emit a lot of very common code.  To reduce the amount of
   // code that we emit, batch up cases that have identical types.  This avoids
   // problems where GCC can run out of memory compiling Verifier.cpp.
-  typedef std::map<std::vector<Record*>, std::vector<unsigned>, 
-    RecordListComparator> MapTy;
+  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
   MapTy UniqueArgInfos;
   
   // Compute the unique argument type info.
   for (unsigned i = 0, e = Ints.size(); i != e; ++i)
-    UniqueArgInfos[Ints[i].ArgTypeDefs].push_back(i);
+    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
+                             Ints[i].IS.ParamTypeDefs)].push_back(i);
 
   // Loop through the array, emitting one comparison for each batch.
   for (MapTy::iterator I = UniqueArgInfos.begin(),
        E = UniqueArgInfos.end(); I != E; ++I) {
-    for (unsigned i = 0, e = I->second.size(); 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";
-    }
     
-    const std::vector<Record*> &ArgTypes = I->first;
-    OS << "    VerifyIntrinsicPrototype(ID, IF, " << ArgTypes.size() << ", ";
-    for (unsigned j = 0; j != ArgTypes.size(); ++j) {
-      Record *ArgType = ArgTypes[j];
+    const RecPair &ArgTypes = I->first;
+    const std::vector<Record*> &RetTys = ArgTypes.first;
+    const std::vector<Record*> &ParamTys = ArgTypes.second;
+
+    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
+       << ParamTys.size();
+
+    // Emit return types.
+    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
+      Record *ArgType = RetTys[j];
+      OS << ", ";
+
       if (ArgType->isSubClassOf("LLVMMatchType")) {
         unsigned Number = ArgType->getValueAsInt("Number");
         assert(Number < j && "Invalid matching number!");
@@ -236,11 +283,28 @@
       } else {
         MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
         OS << getEnumName(VT);
-        if (VT == MVT::isVoid && j != 0 && j != ArgTypes.size()-1)
+
+        if (VT == MVT::isVoid && j != 0 && j != je - 1)
           throw "Var arg type not last argument";
       }
-      if (j != ArgTypes.size()-1)
-        OS << ", ";
+    }
+
+    // Emit the parameter types.
+    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
+      Record *ArgType = ParamTys[j];
+      OS << ", ";
+
+      if (ArgType->isSubClassOf("LLVMMatchType")) {
+        unsigned Number = ArgType->getValueAsInt("Number");
+        assert(Number < j + RetTys.size() && "Invalid matching number!");
+        OS << "~" << Number;
+      } else {
+        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
+        OS << getEnumName(VT);
+
+        if (VT == MVT::isVoid && j != 0 && j != je - 1)
+          throw "Var arg type not last argument";
+      }
     }
       
     OS << ");\n";
@@ -259,43 +323,47 @@
   
   // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
   // types.
-  typedef std::map<std::vector<Record*>, std::vector<unsigned>, 
-    RecordListComparator> MapTy;
+  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
   MapTy UniqueArgInfos;
   
   // Compute the unique argument type info.
   for (unsigned i = 0, e = Ints.size(); i != e; ++i)
-    UniqueArgInfos[Ints[i].ArgTypeDefs].push_back(i);
+    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
+                             Ints[i].IS.ParamTypeDefs)].push_back(i);
 
   // Loop through the array, emitting one generator for each batch.
   for (MapTy::iterator I = UniqueArgInfos.begin(),
        E = UniqueArgInfos.end(); I != E; ++I) {
-    for (unsigned i = 0, e = I->second.size(); 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";
-    }
     
-    const std::vector<Record*> &ArgTypes = I->first;
-    unsigned N = ArgTypes.size();
+    const RecPair &ArgTypes = I->first;
+    const std::vector<Record*> &RetTys = ArgTypes.first;
+    const std::vector<Record*> &ParamTys = ArgTypes.second;
+
+    unsigned N = ParamTys.size();
 
     if (N > 1 &&
-        getValueType(ArgTypes[N-1]->getValueAsDef("VT")) == MVT::isVoid) {
+        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
       OS << "    IsVarArg = true;\n";
       --N;
     }
-    
+
     unsigned ArgNo = 0;
     OS << "    ResultTy = ";
-    EmitTypeGenerate(OS, ArgTypes[0], ArgNo);
+    EmitTypeGenerate(OS, RetTys, ArgNo);
     OS << ";\n";
     
-    for (unsigned j = 1; j != N; ++j) {
+    for (unsigned j = 0; j != N; ++j) {
       OS << "    ArgTys.push_back(";
-      EmitTypeGenerate(OS, ArgTypes[j], ArgNo);
+      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
       OS << ");\n";
     }
+
     OS << "    break;\n";
   }
+
   OS << "  }\n";
   OS << "#endif\n\n";
 }