Revert constant-folding change that will miscompile in some cases.
[oota-llvm.git] / lib / VMCore / Type.cpp
index 4bddeca73fb7794d78b02d37759b864494506dc2..d7fe2d1cfbeea94daec09b222e85331f8d515ea6 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Debug.h"
 #include <algorithm>
+#include <cstdarg>
 using namespace llvm;
 
 // DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are
@@ -436,40 +437,35 @@ const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64);
 //                          Derived Type Constructors
 //===----------------------------------------------------------------------===//
 
-FunctionType::FunctionType(const Type *Result,
-                           const std::vector<const Type*> &Params,
-                           bool IsVarArgs)
-  : DerivedType(FunctionTyID), isVarArgs(IsVarArgs) {
-  ContainedTys = reinterpret_cast<PATypeHandle*>(this+1);
-  NumContainedTys = Params.size() + 1; // + 1 for result type
-  assert((Result->isFirstClassType() || Result == Type::VoidTy ||
-          Result->getTypeID() == Type::StructTyID ||
-          isa<OpaqueType>(Result)) &&
-         "LLVM functions cannot return aggregates");
-  bool isAbstract = Result->isAbstract();
-  new (&ContainedTys[0]) PATypeHandle(Result, this);
-
-  for (unsigned i = 0; i != Params.size(); ++i) {
-    assert((Params[i]->isFirstClassType() || isa<OpaqueType>(Params[i])) &&
-           "Function arguments must be value types!");
-    new (&ContainedTys[i+1]) PATypeHandle(Params[i],this);
-    isAbstract |= Params[i]->isAbstract();
-  }
-
-  // Calculate whether or not this type is abstract
-  setAbstract(isAbstract);
+/// isValidReturnType - Return true if the specified type is valid as a return
+/// type.
+bool FunctionType::isValidReturnType(const Type *RetTy) {
+  if (RetTy->isFirstClassType())
+    return true;
+  if (RetTy == Type::VoidTy || isa<OpaqueType>(RetTy))
+    return true;
+  
+  // If this is a multiple return case, verify that each return is a first class
+  // value and that there is at least one value.
+  const StructType *SRetTy = dyn_cast<StructType>(RetTy);
+  if (SRetTy == 0 || SRetTy->getNumElements() == 0)
+    return false;
+  
+  for (unsigned i = 0, e = SRetTy->getNumElements(); i != e; ++i)
+    if (!SRetTy->getElementType(i)->isFirstClassType())
+      return false;
+  return true;
 }
 
 FunctionType::FunctionType(const Type *Result,
-                           const SmallVectorImpl<const Type *> &Params,
+                           const std::vector<const Type*> &Params,
                            bool IsVarArgs)
   : DerivedType(FunctionTyID), isVarArgs(IsVarArgs) {
   ContainedTys = reinterpret_cast<PATypeHandle*>(this+1);
   NumContainedTys = Params.size() + 1; // + 1 for result type
-  assert((Result->isFirstClassType() || Result == Type::VoidTy ||
-          Result->getTypeID() == Type::StructTyID ||
-          isa<OpaqueType>(Result)) &&
-         "LLVM functions cannot return aggregates");
+  assert(isValidReturnType(Result) && "invalid return type for function");
+    
+    
   bool isAbstract = Result->isAbstract();
   new (&ContainedTys[0]) PATypeHandle(Result, this);
 
@@ -554,6 +550,7 @@ void DerivedType::dropAllTypeUses() {
 }
 
 
+namespace {
 
 /// TypePromotionGraph and graph traits - this is designed to allow us to do
 /// efficient SCC processing of type graphs.  This is the exact same as
@@ -564,6 +561,8 @@ struct TypePromotionGraph {
   TypePromotionGraph(Type *T) : Ty(T) {}
 };
 
+}
+
 namespace llvm {
   template <> struct GraphTraits<TypePromotionGraph> {
     typedef Type NodeType;
@@ -1074,16 +1073,7 @@ class FunctionValType {
   bool isVarArg;
 public:
   FunctionValType(const Type *ret, const std::vector<const Type*> &args,
-                  bool isVA) : RetTy(ret), isVarArg(isVA) {
-    for (unsigned i = 0; i < args.size(); ++i)
-      ArgTypes.push_back(args[i]);
-  }
-
-  FunctionValType(const Type *ret, const SmallVectorImpl<const Type*> &args,
-                  bool isVA) : RetTy(ret), isVarArg(isVA) {
-    for (unsigned i = 0; i < args.size(); ++i)
-      ArgTypes.push_back(args[i]);
-  }
+                  bool isVA) : RetTy(ret), ArgTypes(args), isVarArg(isVA) {}
 
   static FunctionValType get(const FunctionType *FT);
 
@@ -1123,30 +1113,8 @@ FunctionType *FunctionType::get(const Type *ReturnType,
                                 bool isVarArg) {
   FunctionValType VT(ReturnType, Params, isVarArg);
   FunctionType *FT = FunctionTypes->get(VT);
-  if (FT) { 
-    return FT;
-  }
-
-  FT = (FunctionType*) new char[sizeof(FunctionType) + 
-                                sizeof(PATypeHandle)*(Params.size()+1)];
-  new (FT) FunctionType(ReturnType, Params, isVarArg);
-  FunctionTypes->add(VT, FT);
-
-#ifdef DEBUG_MERGE_TYPES
-  DOUT << "Derived new type: " << FT << "\n";
-#endif
-  return FT;
-}
-
-// FunctionType::get - The factory function for the FunctionType class...
-FunctionType *FunctionType::get(const Type *ReturnType,
-                                const SmallVectorImpl<const Type*> &Params,
-                                bool isVarArg) {
-  FunctionValType VT(ReturnType, Params, isVarArg);
-  FunctionType *FT = FunctionTypes->get(VT);
-  if (FT) { 
+  if (FT)
     return FT;
-  }
 
   FT = (FunctionType*) new char[sizeof(FunctionType) + 
                                 sizeof(PATypeHandle)*(Params.size()+1)];
@@ -1301,6 +1269,17 @@ StructType *StructType::get(const std::vector<const Type*> &ETypes,
   return ST;
 }
 
+StructType *StructType::get(const Type *type, ...) {
+  va_list ap;
+  std::vector<const llvm::Type*> StructFields;
+  va_start(ap, type);
+  while (type) {
+    StructFields.push_back(type);
+    type = va_arg(ap, llvm::Type*);
+  }
+  return llvm::StructType::get(StructFields);
+}
+
 
 
 //===----------------------------------------------------------------------===//