Revert constant-folding change that will miscompile in some cases.
[oota-llvm.git] / lib / VMCore / Type.cpp
index 62de6f4fa57b7d021f8358f8957b27a5c4e51eaf..d7fe2d1cfbeea94daec09b222e85331f8d515ea6 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -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,15 +437,35 @@ const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64);
 //                          Derived Type Constructors
 //===----------------------------------------------------------------------===//
 
+/// 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 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 ||
-         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);
 
@@ -529,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
@@ -539,6 +561,8 @@ struct TypePromotionGraph {
   TypePromotionGraph(Type *T) : Ty(T) {}
 };
 
+}
+
 namespace llvm {
   template <> struct GraphTraits<TypePromotionGraph> {
     typedef Type NodeType;
@@ -1049,10 +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]);
-  }
+                  bool isVA) : RetTy(ret), ArgTypes(args), isVarArg(isVA) {}
 
   static FunctionValType get(const FunctionType *FT);
 
@@ -1092,9 +1113,8 @@ FunctionType *FunctionType::get(const Type *ReturnType,
                                 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)];
@@ -1249,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);
+}
+
 
 
 //===----------------------------------------------------------------------===//