For PR1297:
authorReid Spencer <rspencer@reidspencer.com>
Sun, 1 Apr 2007 07:20:02 +0000 (07:20 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Sun, 1 Apr 2007 07:20:02 +0000 (07:20 +0000)
Implement code generation for overloaded intrinsic functions. The basic
difference is that "actual" argument types must be provided when
constructing intrinsic names and types. Also, for recognition, only the
prefix is examined. If it matches, the suffix is assumed to match. The
suffix is checked by the Verifier, however.

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

utils/TableGen/CodeGenIntrinsics.h
utils/TableGen/CodeGenTarget.cpp
utils/TableGen/IntrinsicEmitter.cpp

index 0d1b39bd15d5536d6b434f3946e80705505b0de4..536f3462c52cf8dfc03c518dc1ba7f1ce0ecbd47 100644 (file)
@@ -24,7 +24,7 @@ namespace llvm {
   class CodeGenTarget;
 
   struct CodeGenIntrinsic {
-    Record *TheDef;            // The actual record defining this instruction.
+    Record *TheDef;            // The actual record defining this intrinsic.
     std::string Name;          // The name of the LLVM function "llvm.bswap.i32"
     std::string EnumName;      // The name of the enum "bswap_i32"
     std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "".
@@ -49,6 +49,10 @@ namespace llvm {
       NoMem, ReadArgMem, ReadMem, WriteArgMem, WriteMem
     } ModRef;
 
+    // This is set to true if the intrinsic is overloaded by its argument
+    // types.
+    bool isOverloaded;
+
     CodeGenIntrinsic(Record *R, CodeGenTarget *CGT);
   };
 
index 7cf80b02abef318912c6a1c7baa1db60b676c5a9..151295fc95ec02024a07a2834135b91b7d87df09 100644 (file)
@@ -43,6 +43,7 @@ std::string llvm::getName(MVT::ValueType T) {
   case MVT::i32:   return "MVT::i32";
   case MVT::i64:   return "MVT::i64";
   case MVT::i128:  return "MVT::i128";
+  case MVT::iAny:  return "MVT::iAny";
   case MVT::f32:   return "MVT::f32";
   case MVT::f64:   return "MVT::f64";
   case MVT::f80:   return "MVT::f80";
@@ -74,6 +75,7 @@ std::string llvm::getEnumName(MVT::ValueType T) {
   case MVT::i32:   return "MVT::i32";
   case MVT::i64:   return "MVT::i64";
   case MVT::i128:  return "MVT::i128";
+  case MVT::iAny:  return "MVT::iAny";
   case MVT::f32:   return "MVT::f32";
   case MVT::f64:   return "MVT::f64";
   case MVT::f80:   return "MVT::f80";
@@ -570,6 +572,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R, CodeGenTarget *CGT) {
   TheDef = R;
   std::string DefName = R->getName();
   ModRef = WriteMem;
+  isOverloaded = false;
   
   if (DefName.size() <= 4 || 
       std::string(DefName.begin(), DefName.begin()+4) != "int_")
@@ -610,13 +613,14 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R, CodeGenTarget *CGT) {
     Record *TyEl = TypeList->getElementAsRecord(i);
     assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
     ArgTypes.push_back(TyEl->getValueAsString("TypeVal"));
-    
-    if (CGT)
-      ArgVTs.push_back(getValueType(TyEl->getValueAsDef("VT"), CGT));
+    MVT::ValueType VT = getValueType(TyEl->getValueAsDef("VT"), CGT);
+    isOverloaded |= VT == MVT::iAny;
+    ArgVTs.push_back(VT);
     ArgTypeDefs.push_back(TyEl);
   }
   if (ArgTypes.size() == 0)
     throw "Intrinsic '"+DefName+"' needs at least a type for the ret value!";
+
   
   // Parse the intrinsic properties.
   ListInit *PropList = R->getValueAsListInit("Properties");
index 6247da2af5e6b135ea9cf406935e28dd9e0ec12a..f884c424a71f3c9fd6208fad043ca64f0cb36079 100644 (file)
@@ -74,9 +74,9 @@ void IntrinsicEmitter::
 EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 
                      std::ostream &OS) {
   // Build a function name -> intrinsic name mapping.
-  std::map<std::string, std::string> IntMapping;
+  std::map<std::string, unsigned> IntMapping;
   for (unsigned i = 0, e = Ints.size(); i != e; ++i)
-    IntMapping[Ints[i].Name] = Ints[i].EnumName;
+    IntMapping[Ints[i].Name] = i;
     
   OS << "// Function name -> enum value recognizer code.\n";
   OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
@@ -84,7 +84,7 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "  default:\n";
   // Emit the intrinsics in sorted order.
   char LastChar = 0;
-  for (std::map<std::string, std::string>::iterator I = IntMapping.begin(),
+  for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(),
        E = IntMapping.end(); I != E; ++I) {
     if (I->first[5] != LastChar) {
       LastChar = I->first[5];
@@ -92,9 +92,15 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
       OS << "  case '" << LastChar << "':\n";
     }
     
-    OS << "    if (Len == " << I->first.size()
-       << " && !memcmp(Name, \"" << I->first << "\", Len)) return Intrinsic::"
-       << I->second << ";\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()
+       << ")) return Intrinsic::" << Ints[I->second].EnumName << ";\n";
+    else 
+      OS << "    if (Len == " << I->first.size()
+         << " && !memcmp(Name, \"" << I->first << "\", Len)) return Intrinsic::"
+         << Ints[I->second].EnumName << ";\n";
   }
   OS << "  }\n";
   OS << "  // The 'llvm.' namespace is reserved!\n";
@@ -130,16 +136,20 @@ static bool EmitTypeVerify(std::ostream &OS, Record *ArgType) {
   return false;
 }
 
-static void EmitTypeGenerate(std::ostream &OS, Record *ArgType{
+static void EmitTypeGenerate(std::ostream &OS, Record *ArgType, unsigned ArgNo){
   if (ArgType->isSubClassOf("LLVMIntegerType")) {
-    OS << "IntegerType::get(" << ArgType->getValueAsInt("Width") << ")";
+    unsigned BitWidth = ArgType->getValueAsInt("Width");
+    if (BitWidth == 0)
+      OS << "Tys[" << ArgNo << "]";
+    else
+      OS << "IntegerType::get(" << BitWidth << ")";
   } else if (ArgType->isSubClassOf("LLVMVectorType")) {
     OS << "VectorType::get(";
-    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"));
+    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
     OS << ", " << ArgType->getValueAsInt("NumElts") << ")";
   } else if (ArgType->isSubClassOf("LLVMPointerType")) {
     OS << "PointerType::get(";
-    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"));
+    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
     OS << ")";
   } else if (ArgType->isSubClassOf("LLVMEmptyStructType")) {
     OS << "StructType::get(std::vector<const Type *>())";
@@ -194,7 +204,7 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
     }
     
     const std::vector<Record*> &ArgTypes = I->first;
-    OS << "    VerifyIntrinsicPrototype(IF, ";
+    OS << "    VerifyIntrinsicPrototype(ID, IF, ";
     bool VarArg = false;
     for (unsigned j = 0; j != ArgTypes.size(); ++j) {
       VarArg = EmitTypeVerify(OS, ArgTypes[j]);
@@ -246,12 +256,12 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
     }
     
     OS << "    ResultTy = ";
-    EmitTypeGenerate(OS, ArgTypes[0]);
+    EmitTypeGenerate(OS, ArgTypes[0], 0);
     OS << ";\n";
     
     for (unsigned j = 1; j != N; ++j) {
       OS << "    ArgTys.push_back(";
-      EmitTypeGenerate(OS, ArgTypes[j]);
+      EmitTypeGenerate(OS, ArgTypes[j], j);
       OS << ");\n";
     }