Whether an argument is required (in contrast with being an
optional argument passed through the variadic ellipsis)
potentially affects how we need to lower it.  Propagate
this information down to the various getFunctionInfo(...)
overloads on CodeGenTypes.  Furthermore, rename those
overloads to clarify their distinct purposes, and make
sure we're calling the right one in the right place.
This has a nice side-effect of making it easier to construct
a function type, since the 'variadic' bit is no longer
separable.

This shouldn't really change anything for our existing
platforms, with one minor exception --- we should now call
variadic ObjC methods with the ... in the "right place"
(see the test case), which I guess matters for anyone
running GNUStep on MIPS.  Mostly it's just a substantial
clean-up.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150788 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index e52aed3..a91a341 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -855,11 +855,11 @@
   llvm::Value *Func = Builder.CreateLoad(FuncPtr);
 
   const FunctionType *FuncTy = FnType->castAs<FunctionType>();
-  const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(Args, FuncTy);
+  const CGFunctionInfo &FnInfo =
+    CGM.getTypes().arrangeFunctionCall(Args, FuncTy);
 
   // Cast the function pointer to the right type.
-  llvm::Type *BlockFTy =
-    CGM.getTypes().GetFunctionType(FnInfo, false);
+  llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo);
 
   llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
   Func = Builder.CreateBitCast(Func, BlockFTyPtr);
@@ -1013,16 +1013,15 @@
     args.push_back(*i);
 
   // Create the function declaration.
-  const FunctionProtoType *fnType =
-    cast<FunctionProtoType>(blockInfo.getBlockExpr()->getFunctionType());
+  const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType();
   const CGFunctionInfo &fnInfo =
-    CGM.getTypes().getFunctionInfo(fnType->getResultType(), args,
-                                   fnType->getExtInfo());
+    CGM.getTypes().arrangeFunctionDeclaration(fnType->getResultType(), args,
+                                              fnType->getExtInfo(),
+                                              fnType->isVariadic());
   if (CGM.ReturnTypeUsesSRet(fnInfo))
     blockInfo.UsesStret = true;
 
-  llvm::FunctionType *fnLLVMType =
-    CGM.getTypes().GetFunctionType(fnInfo, fnType->isVariadic());
+  llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo);
 
   MangleBuffer name;
   CGM.getBlockMangledName(GD, name, blockDecl);
@@ -1164,11 +1163,13 @@
   args.push_back(&srcDecl);
 
   const CGFunctionInfo &FI =
-      CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+    CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
+                                              FunctionType::ExtInfo(),
+                                              /*variadic*/ false);
 
   // FIXME: it would be nice if these were mergeable with things with
   // identical semantics.
-  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
 
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
@@ -1279,11 +1280,13 @@
   args.push_back(&srcDecl);
 
   const CGFunctionInfo &FI =
-      CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+    CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
+                                              FunctionType::ExtInfo(),
+                                              /*variadic*/ false);
 
   // FIXME: We'd like to put these into a mergable by content, with
   // internal linkage.
-  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
 
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
@@ -1557,10 +1560,12 @@
   args.push_back(&src);
 
   const CGFunctionInfo &FI =
-    CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo());
+    CGF.CGM.getTypes().arrangeFunctionDeclaration(R, args,
+                                                  FunctionType::ExtInfo(),
+                                                  /*variadic*/ false);
 
   CodeGenTypes &Types = CGF.CGM.getTypes();
-  llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
+  llvm::FunctionType *LTy = Types.GetFunctionType(FI);
 
   // FIXME: We'd like to put these into a mergable by content, with
   // internal linkage.
@@ -1625,10 +1630,12 @@
   args.push_back(&src);
 
   const CGFunctionInfo &FI =
-    CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo());
+    CGF.CGM.getTypes().arrangeFunctionDeclaration(R, args,
+                                                  FunctionType::ExtInfo(),
+                                                  /*variadic*/ false);
 
   CodeGenTypes &Types = CGF.CGM.getTypes();
-  llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
+  llvm::FunctionType *LTy = Types.GetFunctionType(FI);
 
   // FIXME: We'd like to put these into a mergable by content, with
   // internal linkage.
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index b5e6e0d..7c08650 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -196,7 +196,8 @@
                                 GlobalDecl(ctor, Ctor_Base)))
     return;
 
-  const CGFunctionInfo &fnInfo = getTypes().getFunctionInfo(ctor, ctorType);
+  const CGFunctionInfo &fnInfo =
+    getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
 
   llvm::Function *fn =
     cast<llvm::Function>(GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo));
@@ -218,11 +219,10 @@
   if (llvm::GlobalValue *existing = GetGlobalValue(name))
     return existing;
 
-  if (!fnInfo) fnInfo = &getTypes().getFunctionInfo(ctor, ctorType);
+  if (!fnInfo)
+    fnInfo = &getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
 
-  const FunctionProtoType *proto = ctor->getType()->castAs<FunctionProtoType>();
-  llvm::FunctionType *fnType =
-    getTypes().GetFunctionType(*fnInfo, proto->isVariadic());
+  llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo);
   return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
                                                       /*ForVTable=*/false));
 }
@@ -260,7 +260,8 @@
   if (dtorType == Dtor_Base && !TryEmitBaseDestructorAsAlias(dtor))
     return;
 
-  const CGFunctionInfo &fnInfo = getTypes().getFunctionInfo(dtor, dtorType);
+  const CGFunctionInfo &fnInfo =
+    getTypes().arrangeCXXDestructor(dtor, dtorType);
 
   llvm::Function *fn =
     cast<llvm::Function>(GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo));
@@ -282,11 +283,9 @@
   if (llvm::GlobalValue *existing = GetGlobalValue(name))
     return existing;
 
-  if (!fnInfo) fnInfo = &getTypes().getFunctionInfo(dtor, dtorType);
+  if (!fnInfo) fnInfo = &getTypes().arrangeCXXDestructor(dtor, dtorType);
 
-  llvm::FunctionType *fnType =
-    getTypes().GetFunctionType(*fnInfo, false);
-
+  llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo);
   return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
                                                       /*ForVTable=*/false));
 }
@@ -359,12 +358,10 @@
   // -O does that. But need to support -O0 as well.
   if (MD->isVirtual() && Type != Dtor_Base) {
     // Compute the function type we're calling.
-    const CGFunctionInfo *FInfo = 
-    &CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD),
-                                    Dtor_Complete);
-    const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-    llvm::Type *Ty
-      = CGM.getTypes().GetFunctionType(*FInfo, FPT->isVariadic());
+    const CGFunctionInfo &FInfo = 
+      CGM.getTypes().arrangeCXXDestructor(cast<CXXDestructorDecl>(MD),
+                                          Dtor_Complete);
+    llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
 
     llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD);
     Ty = Ty->getPointerTo()->getPointerTo();
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index fc3f45d..befebbe 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -49,9 +49,8 @@
     MPT->getPointeeType()->getAs<FunctionProtoType>();
   const CXXRecordDecl *RD = 
     cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
-  llvm::FunctionType *FTy = 
-    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
-                                   FPT->isVariadic());
+  llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
+                              CGM.getTypes().arrangeCXXMethodType(RD, FPT));
   return llvm::Constant::getNullValue(FTy->getPointerTo());
 }
 
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 6690a69..2c7a049 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -17,6 +17,7 @@
 #include "ABIInfo.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "TargetInfo.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
@@ -66,29 +67,39 @@
   return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType();
 }
 
+/// Arrange the argument and result information for a value of the
+/// given unprototyped function type.
 const CGFunctionInfo &
-CodeGenTypes::getFunctionInfo(CanQual<FunctionNoProtoType> FTNP) {
-  return getFunctionInfo(FTNP->getResultType().getUnqualifiedType(),
-                         SmallVector<CanQualType, 16>(),
-                         FTNP->getExtInfo());
+CodeGenTypes::arrangeFunctionType(CanQual<FunctionNoProtoType> FTNP) {
+  // When translating an unprototyped function type, always use a
+  // variadic type.
+  return arrangeFunctionType(FTNP->getResultType().getUnqualifiedType(),
+                             ArrayRef<CanQualType>(),
+                             FTNP->getExtInfo(),
+                             RequiredArgs(0));
 }
 
-/// \param Args - contains any initial parameters besides those
-///   in the formal type
-static const CGFunctionInfo &getFunctionInfo(CodeGenTypes &CGT,
-                                  SmallVectorImpl<CanQualType> &ArgTys,
+/// Arrange the argument and result information for a value of the
+/// given function type, on top of any implicit parameters already
+/// stored.
+static const CGFunctionInfo &arrangeFunctionType(CodeGenTypes &CGT,
+                                  SmallVectorImpl<CanQualType> &argTypes,
                                              CanQual<FunctionProtoType> FTP) {
+  RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, argTypes.size());
   // FIXME: Kill copy.
   for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
-    ArgTys.push_back(FTP->getArgType(i));
-  CanQualType ResTy = FTP->getResultType().getUnqualifiedType();
-  return CGT.getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
+    argTypes.push_back(FTP->getArgType(i));
+  CanQualType resultType = FTP->getResultType().getUnqualifiedType();
+  return CGT.arrangeFunctionType(resultType, argTypes,
+                                 FTP->getExtInfo(), required);
 }
 
+/// Arrange the argument and result information for a value of the
+/// given function type.
 const CGFunctionInfo &
-CodeGenTypes::getFunctionInfo(CanQual<FunctionProtoType> FTP) {
-  SmallVector<CanQualType, 16> ArgTys;
-  return ::getFunctionInfo(*this, ArgTys, FTP);
+CodeGenTypes::arrangeFunctionType(CanQual<FunctionProtoType> FTP) {
+  SmallVector<CanQualType, 16> argTypes;
+  return ::arrangeFunctionType(*this, argTypes, FTP);
 }
 
 static CallingConv getCallingConventionForDecl(const Decl *D) {
@@ -111,82 +122,133 @@
   return CC_C;
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,
-                                                 const FunctionProtoType *FTP) {
-  SmallVector<CanQualType, 16> ArgTys;
+/// Arrange the argument and result information for a call to an
+/// unknown C++ non-static member function of the given abstract type.
+/// The member function must be an ordinary function, i.e. not a
+/// constructor or destructor.
+const CGFunctionInfo &
+CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
+                                   const FunctionProtoType *FTP) {
+  SmallVector<CanQualType, 16> argTypes;
 
   // Add the 'this' pointer.
-  ArgTys.push_back(GetThisType(Context, RD));
+  argTypes.push_back(GetThisType(Context, RD));
 
-  return ::getFunctionInfo(*this, ArgTys,
+  return ::arrangeFunctionType(*this, argTypes,
               FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
-  SmallVector<CanQualType, 16> ArgTys;
-
+/// Arrange the argument and result information for a declaration or
+/// definition of the given C++ non-static member function.  The
+/// member function must be an ordinary function, i.e. not a
+/// constructor or destructor.
+const CGFunctionInfo &
+CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
   assert(!isa<CXXConstructorDecl>(MD) && "wrong method for contructors!");
   assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
 
-  // Add the 'this' pointer unless this is a static method.
-  if (MD->isInstance())
-    ArgTys.push_back(GetThisType(Context, MD->getParent()));
+  CanQual<FunctionProtoType> prototype = GetFormalType(MD);
 
-  return ::getFunctionInfo(*this, ArgTys, GetFormalType(MD));
+  if (MD->isInstance()) {
+    // The abstract case is perfectly fine.
+    return arrangeCXXMethodType(MD->getParent(), prototype.getTypePtr());
+  }
+
+  return arrangeFunctionType(prototype);
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,
-                                                    CXXCtorType Type) {
-  SmallVector<CanQualType, 16> ArgTys;
-  ArgTys.push_back(GetThisType(Context, D->getParent()));
-  CanQualType ResTy = Context.VoidTy;
+/// Arrange the argument and result information for a declaration
+/// or definition to the given constructor variant.
+const CGFunctionInfo &
+CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
+                                               CXXCtorType ctorKind) {
+  SmallVector<CanQualType, 16> argTypes;
+  argTypes.push_back(GetThisType(Context, D->getParent()));
+  CanQualType resultType = Context.VoidTy;
 
-  TheCXXABI.BuildConstructorSignature(D, Type, ResTy, ArgTys);
+  TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
 
   CanQual<FunctionProtoType> FTP = GetFormalType(D);
 
+  RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, argTypes.size());
+
   // Add the formal parameters.
   for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
-    ArgTys.push_back(FTP->getArgType(i));
+    argTypes.push_back(FTP->getArgType(i));
 
-  return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
+  return arrangeFunctionType(resultType, argTypes, FTP->getExtInfo(), required);
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
-                                                    CXXDtorType Type) {
-  SmallVector<CanQualType, 2> ArgTys;
-  ArgTys.push_back(GetThisType(Context, D->getParent()));
-  CanQualType ResTy = Context.VoidTy;
+/// Arrange the argument and result information for a declaration,
+/// definition, or call to the given destructor variant.  It so
+/// happens that all three cases produce the same information.
+const CGFunctionInfo &
+CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
+                                   CXXDtorType dtorKind) {
+  SmallVector<CanQualType, 2> argTypes;
+  argTypes.push_back(GetThisType(Context, D->getParent()));
+  CanQualType resultType = Context.VoidTy;
 
-  TheCXXABI.BuildDestructorSignature(D, Type, ResTy, ArgTys);
+  TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes);
 
   CanQual<FunctionProtoType> FTP = GetFormalType(D);
   assert(FTP->getNumArgs() == 0 && "dtor with formal parameters");
 
-  return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
+  return arrangeFunctionType(resultType, argTypes, FTP->getExtInfo(),
+                             RequiredArgs::All);
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
+/// Arrange the argument and result information for the declaration or
+/// definition of the given function.
+const CGFunctionInfo &
+CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) {
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
     if (MD->isInstance())
-      return getFunctionInfo(MD);
+      return arrangeCXXMethodDeclaration(MD);
 
   CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified();
+
   assert(isa<FunctionType>(FTy));
-  if (isa<FunctionNoProtoType>(FTy))
-    return getFunctionInfo(FTy.getAs<FunctionNoProtoType>());
+
+  // When declaring a function without a prototype, always use a
+  // non-variadic type.
+  if (isa<FunctionNoProtoType>(FTy)) {
+    CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>();
+    return arrangeFunctionType(noProto->getResultType(),
+                               ArrayRef<CanQualType>(),
+                               noProto->getExtInfo(),
+                               RequiredArgs::All);
+  }
+
   assert(isa<FunctionProtoType>(FTy));
-  return getFunctionInfo(FTy.getAs<FunctionProtoType>());
+  return arrangeFunctionType(FTy.getAs<FunctionProtoType>());
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) {
-  SmallVector<CanQualType, 16> ArgTys;
-  ArgTys.push_back(Context.getCanonicalParamType(MD->getSelfDecl()->getType()));
-  ArgTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
+/// Arrange the argument and result information for the declaration or
+/// definition of an Objective-C method.
+const CGFunctionInfo &
+CodeGenTypes::arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD) {
+  // It happens that this is the same as a call with no optional
+  // arguments, except also using the formal 'self' type.
+  return arrangeObjCMessageSendSignature(MD, MD->getSelfDecl()->getType());
+}
+
+/// Arrange the argument and result information for the function type
+/// through which to perform a send to the given Objective-C method,
+/// using the given receiver type.  The receiver type is not always
+/// the 'self' type of the method or even an Objective-C pointer type.
+/// This is *not* the right method for actually performing such a
+/// message send, due to the possibility of optional arguments.
+const CGFunctionInfo &
+CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
+                                              QualType receiverType) {
+  SmallVector<CanQualType, 16> argTys;
+  argTys.push_back(Context.getCanonicalParamType(receiverType));
+  argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
   // FIXME: Kill copy?
   for (ObjCMethodDecl::param_const_iterator i = MD->param_begin(),
          e = MD->param_end(); i != e; ++i) {
-    ArgTys.push_back(Context.getCanonicalParamType((*i)->getType()));
+    argTys.push_back(Context.getCanonicalParamType((*i)->getType()));
   }
 
   FunctionType::ExtInfo einfo;
@@ -196,77 +258,114 @@
       MD->hasAttr<NSReturnsRetainedAttr>())
     einfo = einfo.withProducesResult(true);
 
-  return getFunctionInfo(GetReturnType(MD->getResultType()), ArgTys, einfo);
+  RequiredArgs required =
+    (MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All);
+
+  return arrangeFunctionType(GetReturnType(MD->getResultType()), argTys,
+                             einfo, required);
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(GlobalDecl GD) {
+const CGFunctionInfo &
+CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
   // FIXME: Do we need to handle ObjCMethodDecl?
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
 
   if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
-    return getFunctionInfo(CD, GD.getCtorType());
+    return arrangeCXXConstructorDeclaration(CD, GD.getCtorType());
 
   if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD))
-    return getFunctionInfo(DD, GD.getDtorType());
+    return arrangeCXXDestructor(DD, GD.getDtorType());
 
-  return getFunctionInfo(FD);
+  return arrangeFunctionDeclaration(FD);
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
-                                                    const CallArgList &Args,
-                                            const FunctionType::ExtInfo &Info) {
+/// Figure out the rules for calling a function with the given formal
+/// type using the given arguments.  The arguments are necessary
+/// because the function might be unprototyped, in which case it's
+/// target-dependent in crazy ways.
+const CGFunctionInfo &
+CodeGenTypes::arrangeFunctionCall(const CallArgList &args,
+                                  const FunctionType *fnType) {
+  RequiredArgs required = RequiredArgs::All;
+  if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) {
+    if (proto->isVariadic())
+      required = RequiredArgs(proto->getNumArgs());
+  } else if (CGM.getTargetCodeGenInfo()
+               .isNoProtoCallVariadic(args, cast<FunctionNoProtoType>(fnType))) {
+    required = RequiredArgs(0);
+  }
+
+  return arrangeFunctionCall(fnType->getResultType(), args,
+                             fnType->getExtInfo(), required);
+}
+
+const CGFunctionInfo &
+CodeGenTypes::arrangeFunctionCall(QualType resultType,
+                                  const CallArgList &args,
+                                  const FunctionType::ExtInfo &info,
+                                  RequiredArgs required) {
   // FIXME: Kill copy.
-  SmallVector<CanQualType, 16> ArgTys;
-  for (CallArgList::const_iterator i = Args.begin(), e = Args.end();
+  SmallVector<CanQualType, 16> argTypes;
+  for (CallArgList::const_iterator i = args.begin(), e = args.end();
        i != e; ++i)
-    ArgTys.push_back(Context.getCanonicalParamType(i->Ty));
-  return getFunctionInfo(GetReturnType(ResTy), ArgTys, Info);
+    argTypes.push_back(Context.getCanonicalParamType(i->Ty));
+  return arrangeFunctionType(GetReturnType(resultType), argTypes, info,
+                             required);
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
-                                                    const FunctionArgList &Args,
-                                            const FunctionType::ExtInfo &Info) {
+const CGFunctionInfo &
+CodeGenTypes::arrangeFunctionDeclaration(QualType resultType,
+                                         const FunctionArgList &args,
+                                         const FunctionType::ExtInfo &info,
+                                         bool isVariadic) {
   // FIXME: Kill copy.
-  SmallVector<CanQualType, 16> ArgTys;
-  for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
+  SmallVector<CanQualType, 16> argTypes;
+  for (FunctionArgList::const_iterator i = args.begin(), e = args.end();
        i != e; ++i)
-    ArgTys.push_back(Context.getCanonicalParamType((*i)->getType()));
-  return getFunctionInfo(GetReturnType(ResTy), ArgTys, Info);
+    argTypes.push_back(Context.getCanonicalParamType((*i)->getType()));
+
+  RequiredArgs required =
+    (isVariadic ? RequiredArgs(args.size()) : RequiredArgs::All);
+  return arrangeFunctionType(GetReturnType(resultType), argTypes, info,
+                             required);
 }
 
-const CGFunctionInfo &CodeGenTypes::getNullaryFunctionInfo() {
-  SmallVector<CanQualType, 1> args;
-  return getFunctionInfo(getContext().VoidTy, args, FunctionType::ExtInfo());
+const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
+  return arrangeFunctionType(getContext().VoidTy, ArrayRef<CanQualType>(),
+                             FunctionType::ExtInfo(), RequiredArgs::All);
 }
 
-const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
-                           const SmallVectorImpl<CanQualType> &ArgTys,
-                                            const FunctionType::ExtInfo &Info) {
+/// Arrange the argument and result information for an abstract value
+/// of a given function type.  This is the method which all of the
+/// above functions ultimately defer to.
+const CGFunctionInfo &
+CodeGenTypes::arrangeFunctionType(CanQualType resultType,
+                                  ArrayRef<CanQualType> argTypes,
+                                  const FunctionType::ExtInfo &info,
+                                  RequiredArgs required) {
 #ifndef NDEBUG
-  for (SmallVectorImpl<CanQualType>::const_iterator
-         I = ArgTys.begin(), E = ArgTys.end(); I != E; ++I)
+  for (ArrayRef<CanQualType>::const_iterator
+         I = argTypes.begin(), E = argTypes.end(); I != E; ++I)
     assert(I->isCanonicalAsParam());
 #endif
 
-  unsigned CC = ClangCallConvToLLVMCallConv(Info.getCC());
+  unsigned CC = ClangCallConvToLLVMCallConv(info.getCC());
 
   // Lookup or create unique function info.
   llvm::FoldingSetNodeID ID;
-  CGFunctionInfo::Profile(ID, Info, ResTy, ArgTys.begin(), ArgTys.end());
+  CGFunctionInfo::Profile(ID, info, required, resultType, argTypes);
 
-  void *InsertPos = 0;
-  CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, InsertPos);
+  void *insertPos = 0;
+  CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
   if (FI)
     return *FI;
 
-  // Construct the function info.
-  FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getProducesResult(),
-                          Info.getHasRegParm(), Info.getRegParm(), ResTy,
-                          ArgTys.data(), ArgTys.size());
-  FunctionInfos.InsertNode(FI, InsertPos);
+  // Construct the function info.  We co-allocate the ArgInfos.
+  FI = CGFunctionInfo::create(CC, info, resultType, argTypes, required);
+  FunctionInfos.InsertNode(FI, insertPos);
 
-  bool Inserted = FunctionsBeingProcessed.insert(FI); (void)Inserted;
-  assert(Inserted && "Recursively being processed?");
+  bool inserted = FunctionsBeingProcessed.insert(FI); (void)inserted;
+  assert(inserted && "Recursively being processed?");
   
   // Compute ABI information.
   getABIInfo().computeInfo(*FI);
@@ -274,39 +373,42 @@
   // Loop over all of the computed argument and return value info.  If any of
   // them are direct or extend without a specified coerce type, specify the
   // default now.
-  ABIArgInfo &RetInfo = FI->getReturnInfo();
-  if (RetInfo.canHaveCoerceToType() && RetInfo.getCoerceToType() == 0)
-    RetInfo.setCoerceToType(ConvertType(FI->getReturnType()));
+  ABIArgInfo &retInfo = FI->getReturnInfo();
+  if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == 0)
+    retInfo.setCoerceToType(ConvertType(FI->getReturnType()));
 
   for (CGFunctionInfo::arg_iterator I = FI->arg_begin(), E = FI->arg_end();
        I != E; ++I)
     if (I->info.canHaveCoerceToType() && I->info.getCoerceToType() == 0)
       I->info.setCoerceToType(ConvertType(I->type));
 
-  bool Erased = FunctionsBeingProcessed.erase(FI); (void)Erased;
-  assert(Erased && "Not in set?");
+  bool erased = FunctionsBeingProcessed.erase(FI); (void)erased;
+  assert(erased && "Not in set?");
   
   return *FI;
 }
 
-CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,
-                               bool _NoReturn, bool returnsRetained,
-                               bool _HasRegParm, unsigned _RegParm,
-                               CanQualType ResTy,
-                               const CanQualType *ArgTys,
-                               unsigned NumArgTys)
-  : CallingConvention(_CallingConvention),
-    EffectiveCallingConvention(_CallingConvention),
-    NoReturn(_NoReturn), ReturnsRetained(returnsRetained),
-    HasRegParm(_HasRegParm), RegParm(_RegParm)
-{
-  NumArgs = NumArgTys;
-
-  // FIXME: Coallocate with the CGFunctionInfo object.
-  Args = new ArgInfo[1 + NumArgTys];
-  Args[0].type = ResTy;
-  for (unsigned i = 0; i != NumArgTys; ++i)
-    Args[1 + i].type = ArgTys[i];
+CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
+                                       const FunctionType::ExtInfo &info,
+                                       CanQualType resultType,
+                                       ArrayRef<CanQualType> argTypes,
+                                       RequiredArgs required) {
+  void *buffer = operator new(sizeof(CGFunctionInfo) +
+                              sizeof(ArgInfo) * (argTypes.size() + 1));
+  CGFunctionInfo *FI = new(buffer) CGFunctionInfo();
+  FI->CallingConvention = llvmCC;
+  FI->EffectiveCallingConvention = llvmCC;
+  FI->ASTCallingConvention = info.getCC();
+  FI->NoReturn = info.getNoReturn();
+  FI->ReturnsRetained = info.getProducesResult();
+  FI->Required = required;
+  FI->HasRegParm = info.getHasRegParm();
+  FI->RegParm = info.getRegParm();
+  FI->NumArgs = argTypes.size();
+  FI->getArgsBuffer()[0].type = resultType;
+  for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
+    FI->getArgsBuffer()[i + 1].type = argTypes[i];
+  return FI;
 }
 
 /***/
@@ -623,19 +725,12 @@
 }
 
 llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) {
-  const CGFunctionInfo &FI = getFunctionInfo(GD);
-
-  // For definition purposes, don't consider a K&R function variadic.
-  bool Variadic = false;
-  if (const FunctionProtoType *FPT =
-        cast<FunctionDecl>(GD.getDecl())->getType()->getAs<FunctionProtoType>())
-    Variadic = FPT->isVariadic();
-
-  return GetFunctionType(FI, Variadic);
+  const CGFunctionInfo &FI = arrangeGlobalDeclaration(GD);
+  return GetFunctionType(FI);
 }
 
 llvm::FunctionType *
-CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool isVariadic) {
+CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
   
   bool Inserted = FunctionsBeingProcessed.insert(&FI); (void)Inserted;
   assert(Inserted && "Recursively being processed?");
@@ -711,7 +806,7 @@
   bool Erased = FunctionsBeingProcessed.erase(&FI); (void)Erased;
   assert(Erased && "Not in set?");
   
-  return llvm::FunctionType::get(resultType, argTypes, isVariadic);
+  return llvm::FunctionType::get(resultType, argTypes, FI.isVariadic());
 }
 
 llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
@@ -723,10 +818,10 @@
     
   const CGFunctionInfo *Info;
   if (isa<CXXDestructorDecl>(MD))
-    Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
+    Info = &arrangeCXXDestructor(cast<CXXDestructorDecl>(MD), GD.getDtorType());
   else
-    Info = &getFunctionInfo(MD);
-  return GetFunctionType(*Info, FPT->isVariadic());
+    Info = &arrangeCXXMethodDeclaration(MD);
+  return GetFunctionType(*Info);
 }
 
 void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 24ed366..dead7bd 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -98,6 +98,55 @@
     SmallVector<Writeback, 1> Writebacks;
   };
 
+  /// A class for recording the number of arguments that a function
+  /// signature requires.
+  class RequiredArgs {
+    /// The number of required arguments, or ~0 if the signature does
+    /// not permit optional arguments.
+    unsigned NumRequired;
+  public:
+    enum All_t { All };
+
+    RequiredArgs(All_t _) : NumRequired(~0U) {}
+    explicit RequiredArgs(unsigned n) : NumRequired(n) {
+      assert(n != ~0U);
+    }
+
+    /// Compute the arguments required by the given formal prototype,
+    /// given that there may be some additional, non-formal arguments
+    /// in play.
+    static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
+                                         unsigned additional) {
+      if (!prototype->isVariadic()) return All;
+      return RequiredArgs(prototype->getNumArgs() + additional);
+    }
+
+    static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
+      return forPrototypePlus(prototype, 0);
+    }
+
+    static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
+      return forPrototype(prototype.getTypePtr());
+    }
+
+    static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
+                                         unsigned additional) {
+      return forPrototypePlus(prototype.getTypePtr(), additional);
+    }
+
+    bool allowsOptionalArgs() const { return NumRequired != ~0U; }
+    bool getNumRequiredArgs() const {
+      assert(allowsOptionalArgs());
+      return NumRequired;
+    }
+
+    unsigned getOpaqueData() const { return NumRequired; }
+    static RequiredArgs getFromOpaqueData(unsigned value) {
+      if (value == ~0U) return All;
+      return RequiredArgs(value);
+    }
+  };
+
   /// FunctionArgList - Type for representing both the decl and type
   /// of parameters to a function. The decl must be either a
   /// ParmVarDecl or ImplicitParamDecl.
@@ -114,50 +163,71 @@
 
     /// The LLVM::CallingConv to use for this function (as specified by the
     /// user).
-    unsigned CallingConvention;
+    unsigned CallingConvention : 8;
 
     /// The LLVM::CallingConv to actually use for this function, which may
     /// depend on the ABI.
-    unsigned EffectiveCallingConvention;
+    unsigned EffectiveCallingConvention : 8;
+
+    /// The clang::CallingConv that this was originally created with.
+    unsigned ASTCallingConvention : 8;
 
     /// Whether this function is noreturn.
-    bool NoReturn;
+    unsigned NoReturn : 1;
 
     /// Whether this function is returns-retained.
-    bool ReturnsRetained;
-
-    unsigned NumArgs;
-    ArgInfo *Args;
+    unsigned ReturnsRetained : 1;
 
     /// How many arguments to pass inreg.
-    bool HasRegParm;
-    unsigned RegParm;
+    unsigned HasRegParm : 1;
+    unsigned RegParm : 4;
+
+    RequiredArgs Required;
+
+    unsigned NumArgs;
+    ArgInfo *getArgsBuffer() {
+      return reinterpret_cast<ArgInfo*>(this+1);
+    }
+    const ArgInfo *getArgsBuffer() const {
+      return reinterpret_cast<const ArgInfo*>(this + 1);
+    }
+
+    CGFunctionInfo() : Required(RequiredArgs::All) {}
 
   public:
+    static CGFunctionInfo *create(unsigned llvmCC,
+                                  const FunctionType::ExtInfo &extInfo,
+                                  CanQualType resultType,
+                                  ArrayRef<CanQualType> argTypes,
+                                  RequiredArgs required);
+
     typedef const ArgInfo *const_arg_iterator;
     typedef ArgInfo *arg_iterator;
 
-    CGFunctionInfo(unsigned CallingConvention, bool NoReturn,
-                   bool ReturnsRetained, bool HasRegParm, unsigned RegParm,
-                   CanQualType ResTy,
-                   const CanQualType *ArgTys, unsigned NumArgTys);
-    ~CGFunctionInfo() { delete[] Args; }
-
-    const_arg_iterator arg_begin() const { return Args + 1; }
-    const_arg_iterator arg_end() const { return Args + 1 + NumArgs; }
-    arg_iterator arg_begin() { return Args + 1; }
-    arg_iterator arg_end() { return Args + 1 + NumArgs; }
+    const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
+    const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
+    arg_iterator arg_begin() { return getArgsBuffer() + 1; }
+    arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
 
     unsigned  arg_size() const { return NumArgs; }
 
+    bool isVariadic() const { return Required.allowsOptionalArgs(); }
+    RequiredArgs getRequiredArgs() const { return Required; }
+
     bool isNoReturn() const { return NoReturn; }
 
-    /// In ARR, whether this function retains its return value.  This
+    /// In ARC, whether this function retains its return value.  This
     /// is not always reliable for call sites.
     bool isReturnsRetained() const { return ReturnsRetained; }
 
-    /// getCallingConvention - Return the user specified calling
+    /// getASTCallingConvention() - Return the AST-specified calling
     /// convention.
+    CallingConv getASTCallingConvention() const {
+      return CallingConv(ASTCallingConvention);
+    }
+
+    /// getCallingConvention - Return the user specified calling
+    /// convention, which has been translated into an LLVM CC.
     unsigned getCallingConvention() const { return CallingConvention; }
 
     /// getEffectiveCallingConvention - Return the actual calling convention to
@@ -172,36 +242,44 @@
     bool getHasRegParm() const { return HasRegParm; }
     unsigned getRegParm() const { return RegParm; }
 
-    CanQualType getReturnType() const { return Args[0].type; }
+    FunctionType::ExtInfo getExtInfo() const {
+      return FunctionType::ExtInfo(isNoReturn(),
+                                   getHasRegParm(), getRegParm(),
+                                   getASTCallingConvention(),
+                                   isReturnsRetained());
+    }
 
-    ABIArgInfo &getReturnInfo() { return Args[0].info; }
-    const ABIArgInfo &getReturnInfo() const { return Args[0].info; }
+    CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
+
+    ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
+    const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
 
     void Profile(llvm::FoldingSetNodeID &ID) {
-      ID.AddInteger(getCallingConvention());
+      ID.AddInteger(getASTCallingConvention());
       ID.AddBoolean(NoReturn);
       ID.AddBoolean(ReturnsRetained);
       ID.AddBoolean(HasRegParm);
       ID.AddInteger(RegParm);
+      ID.AddInteger(Required.getOpaqueData());
       getReturnType().Profile(ID);
       for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
         it->type.Profile(ID);
     }
-    template<class Iterator>
     static void Profile(llvm::FoldingSetNodeID &ID,
-                        const FunctionType::ExtInfo &Info,
-                        CanQualType ResTy,
-                        Iterator begin,
-                        Iterator end) {
-      ID.AddInteger(Info.getCC());
-      ID.AddBoolean(Info.getNoReturn());
-      ID.AddBoolean(Info.getProducesResult());
-      ID.AddBoolean(Info.getHasRegParm());
-      ID.AddInteger(Info.getRegParm());
-      ResTy.Profile(ID);
-      for (; begin != end; ++begin) {
-        CanQualType T = *begin; // force iterator to be over canonical types
-        T.Profile(ID);
+                        const FunctionType::ExtInfo &info,
+                        RequiredArgs required,
+                        CanQualType resultType,
+                        ArrayRef<CanQualType> argTypes) {
+      ID.AddInteger(info.getCC());
+      ID.AddBoolean(info.getNoReturn());
+      ID.AddBoolean(info.getProducesResult());
+      ID.AddBoolean(info.getHasRegParm());
+      ID.AddInteger(info.getRegParm());
+      ID.AddInteger(required.getOpaqueData());
+      resultType.Profile(ID);
+      for (ArrayRef<CanQualType>::iterator
+             i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
+        i->Profile(ID);
       }
     }
   };
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 7e94af3..7b492fb 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1289,7 +1289,7 @@
     EmitCallArg(Args, *Arg, ArgType);
   }
   
-  EmitCall(CGM.getTypes().getFunctionInfo(Args, FPT), Callee,
+  EmitCall(CGM.getTypes().arrangeFunctionCall(Args, FPT), Callee,
            ReturnValueSlot(), Args, D);
 }
 
@@ -1325,7 +1325,7 @@
     EmitDelegateCallArg(DelegateArgs, param);
   }
 
-  EmitCall(CGM.getTypes().getFunctionInfo(Ctor, CtorType),
+  EmitCall(CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor, CtorType),
            CGM.GetAddrOfCXXConstructor(Ctor, CtorType), 
            ReturnValueSlot(), DelegateArgs, Ctor);
 }
@@ -1710,15 +1710,14 @@
 CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E,
                                              const CXXMethodDecl *MD,
                                              llvm::Value *This) {
-  const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
-  llvm::Type *Ty =
-    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
-                                   FPT->isVariadic());
+  llvm::FunctionType *fnType =
+    CGM.getTypes().GetFunctionType(
+                             CGM.getTypes().arrangeCXXMethodDeclaration(MD));
 
   if (UseVirtualCall(getContext(), E, MD))
-    return BuildVirtualCall(MD, This, Ty);
+    return BuildVirtualCall(MD, This, fnType);
 
-  return CGM.GetAddrOfFunction(MD, Ty);
+  return CGM.GetAddrOfFunction(MD, fnType);
 }
 
 void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
@@ -1750,9 +1749,10 @@
 
   // Get the address of the call operator.
   GlobalDecl GD(CallOperator);
-  const CGFunctionInfo &CalleeFnInfo = CGM.getTypes().getFunctionInfo(GD);
-  llvm::Type *Ty =
-    CGM.getTypes().GetFunctionType(CalleeFnInfo, FPT->isVariadic());
+  const CGFunctionInfo &CalleeFnInfo =
+    CGM.getTypes().arrangeFunctionCall(ResultType, CallArgs, FPT->getExtInfo(),
+                                       RequiredArgs::forPrototypePlus(FPT, 1));
+  llvm::Type *Ty = CGM.getTypes().GetFunctionType(CalleeFnInfo);
   llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
 
   // Determine whether we have a return value slot to use.
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 2de1984..0ee3fcd 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -1184,7 +1184,7 @@
     llvm::Constant *F = CGM.GetAddrOfFunction(FD);
     assert(F && "Could not find function!");
 
-    const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
+    const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD);
     EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D);
   }
 
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 44acf62..1897608 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -277,7 +277,7 @@
                                                  llvm::GlobalVariable *Addr,
                                                        bool PerformInit) {
   StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
-                getTypes().getNullaryFunctionInfo(),
+                getTypes().arrangeNullaryFunction(),
                 FunctionArgList(), SourceLocation());
 
   // Use guarded initialization if the global variable is weak. This
@@ -297,7 +297,7 @@
                                                 llvm::Constant **Decls,
                                                 unsigned NumDecls) {
   StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
-                getTypes().getNullaryFunctionInfo(),
+                getTypes().arrangeNullaryFunction(),
                 FunctionArgList(), SourceLocation());
 
   RunCleanupsScope Scope(*this);
@@ -322,7 +322,7 @@
                   const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
                                                 &DtorsAndObjects) {
   StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
-                getTypes().getNullaryFunctionInfo(),
+                getTypes().arrangeNullaryFunction(),
                 FunctionArgList(), SourceLocation());
 
   // Emit the dtors, in reverse order from construction.
@@ -350,9 +350,10 @@
   args.push_back(&dst);
   
   const CGFunctionInfo &FI = 
-    CGM.getTypes().getFunctionInfo(getContext().VoidTy, args, 
-                                   FunctionType::ExtInfo());
-  llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
+    CGM.getTypes().arrangeFunctionDeclaration(getContext().VoidTy, args,
+                                              FunctionType::ExtInfo(),
+                                              /*variadic*/ false);
+  llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
   llvm::Function *fn = 
     CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
 
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index f67025a..3871f33 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -2454,7 +2454,8 @@
   CallArgList Args;
   EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
 
-  const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(Args, FnType);
+  const CGFunctionInfo &FnInfo =
+    CGM.getTypes().arrangeFunctionCall(Args, FnType);
 
   // C99 6.5.2.2p6:
   //   If the expression that denotes the called function has a type
@@ -2473,11 +2474,8 @@
   // through an unprototyped function type works like a *non-variadic*
   // call.  The way we make this work is to cast to the exact type
   // of the promoted arguments.
-  if (isa<FunctionNoProtoType>(FnType) &&
-      !getTargetHooks().isNoProtoCallVariadic(FnInfo)) {
-    assert(cast<llvm::FunctionType>(Callee->getType()->getContainedType(0))
-             ->isVarArg());
-    llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo, false);
+  if (isa<FunctionNoProtoType>(FnType) && !FnInfo.isVariadic()) {
+    llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo);
     CalleeTy = CalleeTy->getPointerTo();
     Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast");
   }
@@ -2678,7 +2676,8 @@
     Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)),
              getContext().getSizeType());
     const CGFunctionInfo &FuncInfo =
-        CGM.getTypes().getFunctionInfo(RetTy, Args, FunctionType::ExtInfo());
+        CGM.getTypes().arrangeFunctionCall(RetTy, Args, FunctionType::ExtInfo(),
+                                           /*variadic*/ false);
     llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo, false);
     llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName);
     RValue Res = EmitCall(FuncInfo, Func, ReturnValueSlot(), Args);
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 47e5703..548bbc9 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -33,8 +33,6 @@
   assert(MD->isInstance() &&
          "Trying to emit a member call expr on a static method!");
 
-  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-
   CallArgList Args;
 
   // Push the this ptr.
@@ -45,13 +43,16 @@
     QualType T = getContext().getPointerType(getContext().VoidPtrTy);
     Args.add(RValue::get(VTT), T);
   }
+
+  const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
+  RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, Args.size());
   
-  // And the rest of the call args
+  // And the rest of the call args.
   EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
 
-  QualType ResultType = FPT->getResultType();
-  return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
-                                                 FPT->getExtInfo()),
+  return EmitCall(CGM.getTypes().arrangeFunctionCall(FPT->getResultType(), Args,
+                                                     FPT->getExtInfo(),
+                                                     required),
                   Callee, ReturnValue, Args, MD);
 }
 
@@ -229,17 +230,16 @@
   // Compute the function type we're calling.
   const CGFunctionInfo *FInfo = 0;
   if (isa<CXXDestructorDecl>(MD))
-    FInfo = &CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD),
-                                           Dtor_Complete);
+    FInfo = &CGM.getTypes().arrangeCXXDestructor(cast<CXXDestructorDecl>(MD),
+                                                 Dtor_Complete);
   else if (isa<CXXConstructorDecl>(MD))
-    FInfo = &CGM.getTypes().getFunctionInfo(cast<CXXConstructorDecl>(MD),
-                                            Ctor_Complete);
+    FInfo = &CGM.getTypes().arrangeCXXConstructorDeclaration(
+                                                 cast<CXXConstructorDecl>(MD),
+                                                 Ctor_Complete);
   else
-    FInfo = &CGM.getTypes().getFunctionInfo(MD);
+    FInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(MD);
 
-  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-  llvm::Type *Ty
-    = CGM.getTypes().GetFunctionType(*FInfo, FPT->isVariadic());
+  llvm::Type *Ty = CGM.getTypes().GetFunctionType(*FInfo);
 
   // C++ [class.virtual]p12:
   //   Explicit qualification with the scope operator (5.1) suppresses the
@@ -322,7 +322,7 @@
   
   // And the rest of the call args
   EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end());
-  return EmitCall(CGM.getTypes().getFunctionInfo(Args, FPT), Callee, 
+  return EmitCall(CGM.getTypes().arrangeFunctionCall(Args, FPT), Callee, 
                   ReturnValue, Args);
 }
 
@@ -945,7 +945,7 @@
         DeleteArgs.add(getPlacementArgs()[I], *AI++);
 
       // Call 'operator delete'.
-      CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(DeleteArgs, FPT),
+      CGF.EmitCall(CGF.CGM.getTypes().arrangeFunctionCall(DeleteArgs, FPT),
                    CGF.CGM.GetAddrOfFunction(OperatorDelete),
                    ReturnValueSlot(), DeleteArgs, OperatorDelete);
     }
@@ -1006,7 +1006,7 @@
       }
 
       // Call 'operator delete'.
-      CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(DeleteArgs, FPT),
+      CGF.EmitCall(CGF.CGM.getTypes().arrangeFunctionCall(DeleteArgs, FPT),
                    CGF.CGM.GetAddrOfFunction(OperatorDelete),
                    ReturnValueSlot(), DeleteArgs, OperatorDelete);
     }
@@ -1113,7 +1113,8 @@
     // TODO: kill any unnecessary computations done for the size
     // argument.
   } else {
-    RV = EmitCall(CGM.getTypes().getFunctionInfo(allocatorArgs, allocatorType),
+    RV = EmitCall(CGM.getTypes().arrangeFunctionCall(allocatorArgs,
+                                                     allocatorType),
                   CGM.GetAddrOfFunction(allocator), ReturnValueSlot(),
                   allocatorArgs, allocator);
   }
@@ -1236,7 +1237,7 @@
     DeleteArgs.add(RValue::get(Size), SizeTy);
 
   // Emit the call to delete.
-  EmitCall(CGM.getTypes().getFunctionInfo(DeleteArgs, DeleteFTy),
+  EmitCall(CGM.getTypes().arrangeFunctionCall(DeleteArgs, DeleteFTy),
            CGM.GetAddrOfFunction(DeleteFD), ReturnValueSlot(), 
            DeleteArgs, DeleteFD);
 }
@@ -1283,9 +1284,8 @@
         }
         
         llvm::Type *Ty =
-          CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor,
-                                                               Dtor_Complete),
-                                         /*isVariadic=*/false);
+          CGF.getTypes().GetFunctionType(
+                         CGF.getTypes().arrangeCXXDestructor(Dtor, Dtor_Complete));
           
         llvm::Value *Callee
           = CGF.BuildVirtualCall(Dtor, 
@@ -1393,7 +1393,7 @@
       }
 
       // Emit the call to delete.
-      CGF.EmitCall(CGF.getTypes().getFunctionInfo(Args, DeleteFTy),
+      CGF.EmitCall(CGF.getTypes().arrangeFunctionCall(Args, DeleteFTy),
                    CGF.CGM.GetAddrOfFunction(OperatorDelete),
                    ReturnValueSlot(), Args, OperatorDelete);
     }
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 94bad92..9792017 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -307,7 +307,7 @@
 
   llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD);
 
-  const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD);
+  const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD);
   CGM.SetInternalFunctionAttributes(OMD, Fn, FI);
 
   args.push_back(OMD->getSelfDecl());
@@ -369,8 +369,9 @@
   args.add(RValue::get(CGF.Builder.getInt1(hasStrong)), Context.BoolTy);
 
   llvm::Value *fn = CGF.CGM.getObjCRuntime().GetGetStructFunction();
-  CGF.EmitCall(CGF.getTypes().getFunctionInfo(Context.VoidTy, args,
-                                              FunctionType::ExtInfo()),
+  CGF.EmitCall(CGF.getTypes().arrangeFunctionCall(Context.VoidTy, args,
+                                                  FunctionType::ExtInfo(),
+                                                  RequiredArgs::All),
                fn, ReturnValueSlot(), args);
 }
 
@@ -624,8 +625,9 @@
   
   llvm::Value *copyCppAtomicObjectFn = 
   CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction();
-  CGF.EmitCall(CGF.getTypes().getFunctionInfo(CGF.getContext().VoidTy, args,
-                                              FunctionType::ExtInfo()),
+  CGF.EmitCall(CGF.getTypes().arrangeFunctionCall(CGF.getContext().VoidTy, args,
+                                                  FunctionType::ExtInfo(),
+                                                  RequiredArgs::All),
                copyCppAtomicObjectFn, ReturnValueSlot(), args);
 }
 
@@ -710,8 +712,9 @@
 
     // FIXME: We shouldn't need to get the function info here, the
     // runtime already should have computed it to build the function.
-    RValue RV = EmitCall(getTypes().getFunctionInfo(propType, args,
-                                                    FunctionType::ExtInfo()),
+    RValue RV = EmitCall(getTypes().arrangeFunctionCall(propType, args,
+                                                        FunctionType::ExtInfo(),
+                                                        RequiredArgs::All),
                          getPropertyFn, ReturnValueSlot(), args);
 
     // We need to fix the type here. Ivars with copy & retain are
@@ -811,8 +814,9 @@
   args.add(RValue::get(CGF.Builder.getFalse()), CGF.getContext().BoolTy);
 
   llvm::Value *copyStructFn = CGF.CGM.getObjCRuntime().GetSetStructFunction();
-  CGF.EmitCall(CGF.getTypes().getFunctionInfo(CGF.getContext().VoidTy, args,
-                                              FunctionType::ExtInfo()),
+  CGF.EmitCall(CGF.getTypes().arrangeFunctionCall(CGF.getContext().VoidTy, args,
+                                                  FunctionType::ExtInfo(),
+                                                  RequiredArgs::All),
                copyStructFn, ReturnValueSlot(), args);
 }
 
@@ -847,8 +851,9 @@
   
   llvm::Value *copyCppAtomicObjectFn = 
     CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction();
-  CGF.EmitCall(CGF.getTypes().getFunctionInfo(CGF.getContext().VoidTy, args,
-                                              FunctionType::ExtInfo()),
+  CGF.EmitCall(CGF.getTypes().arrangeFunctionCall(CGF.getContext().VoidTy, args,
+                                                  FunctionType::ExtInfo(),
+                                                  RequiredArgs::All),
                copyCppAtomicObjectFn, ReturnValueSlot(), args);
   
 
@@ -961,8 +966,9 @@
              getContext().BoolTy);
     // FIXME: We shouldn't need to get the function info here, the runtime
     // already should have computed it to build the function.
-    EmitCall(getTypes().getFunctionInfo(getContext().VoidTy, args,
-                                        FunctionType::ExtInfo()),
+    EmitCall(getTypes().arrangeFunctionCall(getContext().VoidTy, args,
+                                            FunctionType::ExtInfo(),
+                                            RequiredArgs::All),
              setPropertyFn, ReturnValueSlot(), args);
     return;
   }
@@ -1321,8 +1327,9 @@
   Args2.add(RValue::get(V), getContext().getObjCIdType());
   // FIXME: We shouldn't need to get the function info here, the runtime already
   // should have computed it to build the function.
-  EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2,
-                                          FunctionType::ExtInfo()),
+  EmitCall(CGM.getTypes().arrangeFunctionCall(getContext().VoidTy, Args2,
+                                              FunctionType::ExtInfo(),
+                                              RequiredArgs::All),
            EnumerationMutationFn, ReturnValueSlot(), Args2);
 
   // Otherwise, or if the mutation function returns, just continue.
@@ -2556,7 +2563,7 @@
 void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) {
   // We just use an inline assembly.
   llvm::FunctionType *extenderType
-    = llvm::FunctionType::get(VoidTy, VoidPtrTy, /*variadic*/ false);
+    = llvm::FunctionType::get(VoidTy, VoidPtrTy, RequiredArgs::All);
   llvm::Value *extender
     = llvm::InlineAsm::get(extenderType,
                            /* assembly */ "",
@@ -2614,9 +2621,11 @@
   args.push_back(&srcDecl);
   
   const CGFunctionInfo &FI =
-    CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+    CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
+                                              FunctionType::ExtInfo(),
+                                              RequiredArgs::All);
   
-  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
   
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
@@ -2702,9 +2711,11 @@
   args.push_back(&srcDecl);
   
   const CGFunctionInfo &FI =
-  CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+  CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args,
+                                            FunctionType::ExtInfo(),
+                                            RequiredArgs::All);
   
-  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
   
   llvm::Function *Fn =
   llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 50ab7d2..3e8b528 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -103,8 +103,6 @@
 /// GNUstep).
 class CGObjCGNU : public CGObjCRuntime {
 protected:
-  /// The module that is using this class
-  CodeGenModule &CGM;
   /// The LLVM module into which output is inserted
   llvm::Module &TheModule;
   /// strut objc_super.  Used for sending messages to super.  This structure
@@ -688,9 +686,9 @@
 
 CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
     unsigned protocolClassVersion)
-  : CGM(cgm), TheModule(CGM.getModule()), VMContext(cgm.getLLVMContext()),
-  ClassPtrAlias(0), MetaClassPtrAlias(0), RuntimeVersion(runtimeABIVersion),
-  ProtocolVersion(protocolClassVersion) {
+  : CGObjCRuntime(cgm), TheModule(CGM.getModule()),
+    VMContext(cgm.getLLVMContext()), ClassPtrAlias(0), MetaClassPtrAlias(0),
+    RuntimeVersion(runtimeABIVersion), ProtocolVersion(protocolClassVersion) {
 
   msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
 
@@ -1037,9 +1035,7 @@
   ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
   ActualArgs.addFrom(CallArgs);
 
-  CodeGenTypes &Types = CGM.getTypes();
-  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
-                                                       FunctionType::ExtInfo());
+  MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
 
   llvm::Value *ReceiverClass = 0;
   if (isCategoryImpl) {
@@ -1092,12 +1088,10 @@
   Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
 
   ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy);
-  llvm::FunctionType *impType =
-    Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
 
   // Get the IMP
   llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd);
-  imp = EnforceType(Builder, imp, llvm::PointerType::getUnqual(impType));
+  imp = EnforceType(Builder, imp, MSI.MessengerType);
 
   llvm::Value *impMD[] = {
       llvm::MDString::get(VMContext, Sel.getAsString()),
@@ -1107,8 +1101,7 @@
   llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
 
   llvm::Instruction *call;
-  RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs,
-      0, &call);
+  RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, 0, &call);
   call->setMetadata(msgSendMDKind, node);
   return msgRet;
 }
@@ -1181,13 +1174,13 @@
    };
   llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
 
-  CodeGenTypes &Types = CGM.getTypes();
   CallArgList ActualArgs;
   ActualArgs.add(RValue::get(Receiver), ASTIdTy);
   ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
   ActualArgs.addFrom(CallArgs);
-  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
-                                                       FunctionType::ExtInfo());
+
+  MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
+
   // Get the IMP to call
   llvm::Value *imp;
 
@@ -1203,7 +1196,7 @@
       if (CGM.ReturnTypeUsesFPRet(ResultType)) {
         imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true),
                                   "objc_msgSend_fpret");
-      } else if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+      } else if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
         // The actual types here don't matter - we're going to bitcast the
         // function anyway
         imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true),
@@ -1217,12 +1210,10 @@
   // Reset the receiver in case the lookup modified it
   ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy, false);
 
-  llvm::FunctionType *impType =
-    Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
-  imp = EnforceType(Builder, imp, llvm::PointerType::getUnqual(impType));
+  imp = EnforceType(Builder, imp, MSI.MessengerType);
 
   llvm::Instruction *call;
-  RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs,
+  RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs,
       0, &call);
   call->setMetadata(msgSendMDKind, node);
 
@@ -2418,7 +2409,7 @@
 
   CodeGenTypes &Types = CGM.getTypes();
   llvm::FunctionType *MethodTy =
-    Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
+    Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
   std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
       MethodName, isClassMethod);
 
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index b489692..d42f9f2 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -241,9 +241,9 @@
     Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
     Params.push_back(Ctx.BoolTy);
     llvm::FunctionType *FTy =
-      Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
-                                                  FunctionType::ExtInfo()),
-                            false);
+      Types.GetFunctionType(Types.arrangeFunctionType(IdType, Params,
+                                                      FunctionType::ExtInfo(),
+                                                      RequiredArgs::All));
     return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
   }
 
@@ -261,9 +261,9 @@
     Params.push_back(Ctx.BoolTy);
     Params.push_back(Ctx.BoolTy);
     llvm::FunctionType *FTy =
-      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
-                                                  FunctionType::ExtInfo()),
-                            false);
+      Types.GetFunctionType(Types.arrangeFunctionType(Ctx.VoidTy, Params,
+                                                      FunctionType::ExtInfo(),
+                                                      RequiredArgs::All));
     return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
   }
 
@@ -279,9 +279,9 @@
     Params.push_back(Ctx.BoolTy);
     Params.push_back(Ctx.BoolTy);
     llvm::FunctionType *FTy =
-      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
-                                                  FunctionType::ExtInfo()),
-                            false);
+      Types.GetFunctionType(Types.arrangeFunctionType(Ctx.VoidTy, Params,
+                                                      FunctionType::ExtInfo(),
+                                                      RequiredArgs::All));
     return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
   }
   
@@ -298,9 +298,9 @@
     Params.push_back(Ctx.VoidPtrTy);
     Params.push_back(Ctx.VoidPtrTy);
     llvm::FunctionType *FTy =
-    Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
-                                                FunctionType::ExtInfo()),
-                          false);
+      Types.GetFunctionType(Types.arrangeFunctionType(Ctx.VoidTy, Params,
+                                                      FunctionType::ExtInfo(),
+                                                      RequiredArgs::All));
     return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
   }
   
@@ -311,9 +311,9 @@
     SmallVector<CanQualType,1> Params;
     Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
     llvm::FunctionType *FTy =
-      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
-                                                  FunctionType::ExtInfo()),
-                            false);
+      Types.GetFunctionType(Types.arrangeFunctionType(Ctx.VoidTy, Params,
+                                                      FunctionType::ExtInfo(),
+                                                      RequiredArgs::All));
     return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
   }
 
@@ -719,7 +719,6 @@
   };
 
 protected:
-  CodeGen::CodeGenModule &CGM;
   llvm::LLVMContext &VMContext;
   // FIXME! May not be needing this after all.
   unsigned ObjCABI;
@@ -904,7 +903,7 @@
 
 public:
   CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
-    CGM(cgm), VMContext(cgm.getLLVMContext()) { }
+    CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
 
   virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
 
@@ -1675,11 +1674,8 @@
   ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
   ActualArgs.addFrom(CallArgs);
 
-  CodeGenTypes &Types = CGM.getTypes();
-  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
-                                                       FunctionType::ExtInfo());
-  llvm::FunctionType *FTy =
-    Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
+  // If we're calling a method, use the formal signature.
+  MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
 
   if (Method)
     assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
@@ -1689,7 +1685,7 @@
   NullReturnState nullReturn;
 
   llvm::Constant *Fn = NULL;
-  if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+  if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
     if (!IsSuper) nullReturn.init(CGF, Arg0);
     Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
       : ObjCTypes.getSendStretFn(IsSuper);
@@ -1717,8 +1713,8 @@
       }
     }
   
-  Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
-  RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
+  Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
+  RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
   return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
                              requiresnullCheck ? Method : 0);
 }
@@ -2683,7 +2679,7 @@
 
   CodeGenTypes &Types = CGM.getTypes();
   llvm::FunctionType *MethodTy =
-    Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
+    Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
   llvm::Function *Method =
     llvm::Function::Create(MethodTy,
                            llvm::GlobalValue::InternalLinkage,
@@ -5766,9 +5762,7 @@
 
   args.insert(args.end(), formalArgs.begin(), formalArgs.end());
 
-  const CGFunctionInfo &fnInfo =
-    CGM.getTypes().getFunctionInfo(resultType, args,
-                                   FunctionType::ExtInfo());
+  MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
 
   NullReturnState nullReturn;
 
@@ -5781,7 +5775,7 @@
   // FIXME: don't use this for that.
   llvm::Constant *fn = 0;
   std::string messageRefName("\01l_");
-  if (CGM.ReturnTypeUsesSRet(fnInfo)) {
+  if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
     if (isSuper) {
       fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
       messageRefName += "objc_msgSendSuper2_stret_fixup";
@@ -5849,13 +5843,9 @@
   llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
   callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
 
-  bool variadic = method ? method->isVariadic() : false;
-  llvm::FunctionType *fnType = 
-    CGF.getTypes().GetFunctionType(fnInfo, variadic);
-  callee = CGF.Builder.CreateBitCast(callee,
-                                     llvm::PointerType::getUnqual(fnType));
+  callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
 
-  RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
+  RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
   return nullReturn.complete(CGF, result, resultType, formalArgs, 
                              requiresnullCheck ? method : 0);
 }
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index df039bb..17557cf 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -327,3 +327,48 @@
   // Emit the body of the statement.
   CGF.EmitStmt(S.getSynchBody());
 }
+
+/// Compute the pointer-to-function type to which a message send
+/// should be casted in order to correctly call the given method
+/// with the given arguments.
+///
+/// \param method - may be null
+/// \param resultType - the result type to use if there's no method
+/// \param argInfo - the actual arguments, including implicit ones
+CGObjCRuntime::MessageSendInfo
+CGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method,
+                                  QualType resultType,
+                                  CallArgList &callArgs) {
+  // If there's a method, use information from that.
+  if (method) {
+    const CGFunctionInfo &signature =
+      CGM.getTypes().arrangeObjCMessageSendSignature(method, callArgs[0].Ty);
+
+    llvm::PointerType *signatureType =
+      CGM.getTypes().GetFunctionType(signature)->getPointerTo();
+
+    // If that's not variadic, there's no need to recompute the ABI
+    // arrangement.
+    if (!signature.isVariadic())
+      return MessageSendInfo(signature, signatureType);
+
+    // Otherwise, there is.
+    FunctionType::ExtInfo einfo = signature.getExtInfo();
+    const CGFunctionInfo &argsInfo =
+      CGM.getTypes().arrangeFunctionCall(resultType, callArgs, einfo,
+                                         signature.getRequiredArgs());
+
+    return MessageSendInfo(argsInfo, signatureType);
+  }
+
+  // There's no method;  just use a default CC.
+  const CGFunctionInfo &argsInfo =
+    CGM.getTypes().arrangeFunctionCall(resultType, callArgs, 
+                                       FunctionType::ExtInfo(),
+                                       RequiredArgs::All);
+
+  // Derive the signature to call from that.
+  llvm::PointerType *signatureType =
+    CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo();
+  return MessageSendInfo(argsInfo, signatureType);
+}
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index 39523c9..0f3cb54 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -63,6 +63,9 @@
 /// Implements runtime-specific code generation functions.
 class CGObjCRuntime {
 protected:
+  CodeGen::CodeGenModule &CGM;
+  CGObjCRuntime(CodeGen::CodeGenModule &CGM) : CGM(CGM) {}
+
   // Utility functions for unified ivar access. These need to
   // eventually be folded into other places (the structure layout
   // code).
@@ -255,6 +258,19 @@
   virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
                                   const CodeGen::CGBlockInfo &blockInfo) = 0;
   virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) = 0;
+
+  struct MessageSendInfo {
+    const CGFunctionInfo &CallInfo;
+    llvm::PointerType *MessengerType;
+
+    MessageSendInfo(const CGFunctionInfo &callInfo,
+                    llvm::PointerType *messengerType)
+      : CallInfo(callInfo), MessengerType(messengerType) {}
+  };
+
+  MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method,
+                                     QualType resultType,
+                                     CallArgList &callArgs);
 };
 
 /// Creates an instance of an Objective-C runtime class.
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index c5383b6..77e9fb3 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -242,8 +242,8 @@
   QualType ResultType = FPT->getResultType();
 
   // Get the original function
-  llvm::Type *Ty =
-    CGM.getTypes().GetFunctionType(FnInfo, /*IsVariadic*/true);
+  assert(FnInfo.isVariadic());
+  llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo);
   llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
   llvm::Function *BaseFn = cast<llvm::Function>(Callee);
 
@@ -351,13 +351,13 @@
 
   // Get our callee.
   llvm::Type *Ty =
-    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(GD),
-                                   FPT->isVariadic());
+    CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD));
   llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
 
 #ifndef NDEBUG
   const CGFunctionInfo &CallFnInfo = 
-    CGM.getTypes().getFunctionInfo(ResultType, CallArgs, FPT->getExtInfo());
+    CGM.getTypes().arrangeFunctionCall(ResultType, CallArgs, FPT->getExtInfo(),
+                                       RequiredArgs::forPrototypePlus(FPT, 1));
   assert(CallFnInfo.getRegParm() == FnInfo.getRegParm() &&
          CallFnInfo.isNoReturn() == FnInfo.isNoReturn() &&
          CallFnInfo.getCallingConvention() == FnInfo.getCallingConvention());
@@ -398,7 +398,7 @@
 void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, 
                                bool UseAvailableExternallyLinkage)
 {
-  const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(GD);
+  const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(GD);
 
   // FIXME: re-use FnInfo in this computation.
   llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index dd613b4..c30fe22 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -66,7 +66,7 @@
   : Context(C), Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M),
     TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags),
     ABI(createCXXABI(*this)), 
-    Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI, CGO),
+    Types(*this),
     TBAA(0),
     VTables(*this), ObjCRuntime(0), OpenCLRuntime(0), CUDARuntime(0),
     DebugInfo(0), ARCData(0), NoObjCARCExceptionsMetadata(0),
@@ -580,7 +580,7 @@
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
 
   if (!IsIncompleteFunction)
-    SetLLVMFunctionAttributes(FD, getTypes().getFunctionInfo(GD), F);
+    SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
 
   // Only a few attributes are set on declarations; these may later be
   // overridden by a definition.
@@ -1600,11 +1600,8 @@
   const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
 
   // Compute the function info and LLVM type.
-  const CGFunctionInfo &FI = getTypes().getFunctionInfo(GD);
-  bool variadic = false;
-  if (const FunctionProtoType *fpt = D->getType()->getAs<FunctionProtoType>())
-    variadic = fpt->isVariadic();
-  llvm::FunctionType *Ty = getTypes().GetFunctionType(FI, variadic);
+  const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
+  llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
 
   // Get or create the prototype for the function.
   llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 16ca7ec..0346519 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -15,6 +15,7 @@
 #include "CGCall.h"
 #include "CGCXXABI.h"
 #include "CGRecordLayout.h"
+#include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclCXX.h"
@@ -26,11 +27,12 @@
 using namespace clang;
 using namespace CodeGen;
 
-CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
-                           const llvm::TargetData &TD, const ABIInfo &Info,
-                           CGCXXABI &CXXABI, const CodeGenOptions &CGO)
-  : Context(Ctx), Target(Ctx.getTargetInfo()), TheModule(M), TheTargetData(TD),
-    TheABIInfo(Info), TheCXXABI(CXXABI), CodeGenOpts(CGO) {
+CodeGenTypes::CodeGenTypes(CodeGenModule &CGM)
+  : Context(CGM.getContext()), Target(Context.getTargetInfo()),
+    TheModule(CGM.getModule()), TheTargetData(CGM.getTargetData()),
+    TheABIInfo(CGM.getTargetCodeGenInfo().getABIInfo()),
+    TheCXXABI(CGM.getCXXABI()),
+    CodeGenOpts(CGM.getCodeGenOpts()), CGM(CGM) {
   SkippedLayout = false;
 }
 
@@ -473,16 +475,13 @@
     // The function type can be built; call the appropriate routines to
     // build it.
     const CGFunctionInfo *FI;
-    bool isVariadic;
     if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) {
-      FI = &getFunctionInfo(
+      FI = &arrangeFunctionType(
                    CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0)));
-      isVariadic = FPT->isVariadic();
     } else {
       const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(FT);
-      FI = &getFunctionInfo(
+      FI = &arrangeFunctionType(
                 CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0)));
-      isVariadic = true;
     }
     
     // If there is something higher level prodding our CGFunctionInfo, then
@@ -494,7 +493,7 @@
     } else {
 
       // Otherwise, we're good to go, go ahead and convert it.
-      ResultType = GetFunctionType(*FI, isVariadic);
+      ResultType = GetFunctionType(*FI);
     }
 
     RecordsBeingLaidOut.erase(Ty);
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 7f0f8ac..ba2b3ae 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -52,10 +52,13 @@
 namespace CodeGen {
   class CGCXXABI;
   class CGRecordLayout;
+  class CodeGenModule;
+  class RequiredArgs;
 
 /// CodeGenTypes - This class organizes the cross-module state that is used
 /// while lowering AST types to LLVM types.
 class CodeGenTypes {
+  // Some of this stuff should probably be left on the CGM.
   ASTContext &Context;
   const TargetInfo &Target;
   llvm::Module &TheModule;
@@ -63,6 +66,7 @@
   const ABIInfo &TheABIInfo;
   CGCXXABI &TheCXXABI;
   const CodeGenOptions &CodeGenOpts;
+  CodeGenModule &CGM;
 
   /// The opaque type map for Objective-C interfaces. All direct
   /// manipulation is done by the runtime interfaces, which are
@@ -101,9 +105,7 @@
   llvm::DenseMap<const Type *, llvm::Type *> TypeCache;
 
 public:
-  CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD,
-               const ABIInfo &Info, CGCXXABI &CXXABI,
-               const CodeGenOptions &Opts);
+  CodeGenTypes(CodeGenModule &CGM);
   ~CodeGenTypes();
 
   const llvm::TargetData &getTargetData() const { return TheTargetData; }
@@ -124,8 +126,7 @@
   llvm::Type *ConvertTypeForMem(QualType T);
 
   /// GetFunctionType - Get the LLVM function type for \arg Info.
-  llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info,
-                                      bool IsVariadic);
+  llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info);
 
   llvm::FunctionType *GetFunctionType(GlobalDecl GD);
 
@@ -148,50 +149,66 @@
 
   /// getNullaryFunctionInfo - Get the function info for a void()
   /// function with standard CC.
-  const CGFunctionInfo &getNullaryFunctionInfo();
+  const CGFunctionInfo &arrangeNullaryFunction();
 
-  /// getFunctionInfo - Get the function info for the specified function decl.
-  const CGFunctionInfo &getFunctionInfo(GlobalDecl GD);
+  // The arrangement methods are split into three families:
+  //   - those meant to drive the signature and prologue/epilogue
+  //     of a function declaration or definition,
+  //   - those meant for the computation of the LLVM type for an abstract
+  //     appearance of a function, and
+  //   - those meant for performing the IR-generation of a call.
+  // They differ mainly in how they deal with optional (i.e. variadic)
+  // arguments, as well as unprototyped functions.
+  //
+  // Key points:
+  // - The CGFunctionInfo for emitting a specific call site must include
+  //   entries for the optional arguments.
+  // - The function type used at the call site must reflect the formal
+  //   signature of the declaration being called, or else the call will
+  //   go awry.
+  // - For the most part, unprototyped functions are called by casting to
+  //   a formal signature inferred from the specific argument types used
+  //   at the call-site.  However, some targets (e.g. x86-64) screw with
+  //   this for compatibility reasons.
 
-  const CGFunctionInfo &getFunctionInfo(const FunctionDecl *FD);
-  const CGFunctionInfo &getFunctionInfo(const CXXMethodDecl *MD);
-  const CGFunctionInfo &getFunctionInfo(const ObjCMethodDecl *MD);
-  const CGFunctionInfo &getFunctionInfo(const CXXConstructorDecl *D,
-                                        CXXCtorType Type);
-  const CGFunctionInfo &getFunctionInfo(const CXXDestructorDecl *D,
-                                        CXXDtorType Type);
+  const CGFunctionInfo &arrangeGlobalDeclaration(GlobalDecl GD);
+  const CGFunctionInfo &arrangeFunctionDeclaration(const FunctionDecl *FD);
+  const CGFunctionInfo &arrangeFunctionDeclaration(QualType ResTy,
+                                                   const FunctionArgList &Args,
+                                             const FunctionType::ExtInfo &Info,
+                                                   bool isVariadic);
 
-  const CGFunctionInfo &getFunctionInfo(const CallArgList &Args,
-                                        const FunctionType *Ty) {
-    return getFunctionInfo(Ty->getResultType(), Args,
-                           Ty->getExtInfo());
-  }
+  const CGFunctionInfo &arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD);
+  const CGFunctionInfo &arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
+                                                        QualType receiverType);
 
-  const CGFunctionInfo &getFunctionInfo(CanQual<FunctionProtoType> Ty);
-  const CGFunctionInfo &getFunctionInfo(CanQual<FunctionNoProtoType> Ty);
+  const CGFunctionInfo &arrangeCXXMethodDeclaration(const CXXMethodDecl *MD);
+  const CGFunctionInfo &arrangeCXXConstructorDeclaration(
+                                                    const CXXConstructorDecl *D,
+                                                    CXXCtorType Type);
+  const CGFunctionInfo &arrangeCXXDestructor(const CXXDestructorDecl *D,
+                                             CXXDtorType Type);
 
-  /// getFunctionInfo - Get the function info for a member function of
-  /// the given type.  This is used for calls through member function
-  /// pointers.
-  const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
-                                        const FunctionProtoType *FTP);
+  const CGFunctionInfo &arrangeFunctionCall(const CallArgList &Args,
+                                            const FunctionType *Ty);
+  const CGFunctionInfo &arrangeFunctionCall(QualType ResTy,
+                                            const CallArgList &args,
+                                            const FunctionType::ExtInfo &info,
+                                            RequiredArgs required);
 
-  /// getFunctionInfo - Get the function info for a function described by a
-  /// return type and argument types. If the calling convention is not
-  /// specified, the "C" calling convention will be used.
-  const CGFunctionInfo &getFunctionInfo(QualType ResTy,
-                                        const CallArgList &Args,
-                                        const FunctionType::ExtInfo &Info);
-  const CGFunctionInfo &getFunctionInfo(QualType ResTy,
-                                        const FunctionArgList &Args,
-                                        const FunctionType::ExtInfo &Info);
+  const CGFunctionInfo &arrangeFunctionType(CanQual<FunctionProtoType> Ty);
+  const CGFunctionInfo &arrangeFunctionType(CanQual<FunctionNoProtoType> Ty);
+  const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
+                                             const FunctionProtoType *FTP);
 
   /// Retrieves the ABI information for the given function signature.
+  /// This is the "core" routine to which all the others defer.
   ///
-  /// \param ArgTys - must all actually be canonical as params
-  const CGFunctionInfo &getFunctionInfo(CanQualType RetTy,
-                               const SmallVectorImpl<CanQualType> &ArgTys,
-                                        const FunctionType::ExtInfo &Info);
+  /// \param argTypes - must all actually be canonical as params
+  const CGFunctionInfo &arrangeFunctionType(CanQualType returnType,
+                                            ArrayRef<CanQualType> argTypes,
+                                            const FunctionType::ExtInfo &info,
+                                            RequiredArgs args);
 
   /// \brief Compute a new LLVM record layout object for the given record.
   CGRecordLayout *ComputeRecordLayout(const RecordDecl *D,
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 8d06b60..68f2f1d 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -218,8 +218,8 @@
     cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
 
   llvm::FunctionType *FTy = 
-    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
-                                   FPT->isVariadic());
+    CGM.getTypes().GetFunctionType(
+      CGM.getTypes().arrangeCXXMethodType(RD, FPT));
 
   llvm::IntegerType *ptrdiff = getPtrDiffTy();
   llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1);
@@ -511,8 +511,7 @@
     // Check whether the function has a computable LLVM signature.
     if (Types.isFuncTypeConvertible(FPT)) {
       // The function has a computable LLVM signature; use the correct type.
-      Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
-                                 FPT->isVariadic());
+      Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
     } else {
       // Use an arbitrary non-function type to tell GetAddrOfFunction that the
       // function type is incomplete.
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index cae8f5f..2ee662c 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -98,8 +98,8 @@
   return 32;
 }
 
-bool TargetCodeGenInfo::isNoProtoCallVariadic(
-                                       const CodeGen::CGFunctionInfo &) const {
+bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args,
+                                     const FunctionNoProtoType *fnType) const {
   // The following conventions are known to require this to be false:
   //   x86_stdcall
   //   MIPS
@@ -935,6 +935,17 @@
   X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, bool hasavx) :
       ABIInfo(CGT), HasAVX(hasavx) {}
 
+  bool isPassedUsingAVXType(QualType type) const {
+    unsigned neededInt, neededSSE;
+    ABIArgInfo info = classifyArgumentType(type, neededInt, neededSSE);
+    if (info.isDirect()) {
+      llvm::Type *ty = info.getCoerceToType();
+      if (llvm::VectorType *vectorTy = dyn_cast_or_null<llvm::VectorType>(ty))
+        return (vectorTy->getBitWidth() > 128);
+    }
+    return false;
+  }
+
   virtual void computeInfo(CGFunctionInfo &FI) const;
 
   virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -960,6 +971,10 @@
   X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
     : TargetCodeGenInfo(new X86_64ABIInfo(CGT, HasAVX)) {}
 
+  const X86_64ABIInfo &getABIInfo() const {
+    return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo());
+  }
+
   int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
     return 7;
   }
@@ -980,33 +995,29 @@
     return X86AdjustInlineAsmType(CGF, Constraint, Ty);
   }
 
-  bool isNoProtoCallVariadic(const CodeGen::CGFunctionInfo &FI) const {
+  bool isNoProtoCallVariadic(const CallArgList &args,
+                             const FunctionNoProtoType *fnType) const {
     // The default CC on x86-64 sets %al to the number of SSA
     // registers used, and GCC sets this when calling an unprototyped
     // function, so we override the default behavior.  However, don't do
     // that when AVX types are involved: the ABI explicitly states it is
     // undefined, and it doesn't work in practice because of how the ABI
     // defines varargs anyway.
-    if (FI.getCallingConvention() == llvm::CallingConv::C) {
+    if (fnType->getCallConv() == CC_Default || fnType->getCallConv() == CC_C) {
       bool HasAVXType = false;
-      for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
-                                              ie = FI.arg_end();
-           it != ie; ++it) {
-        if (it->info.isDirect()) {
-          llvm::Type *Ty = it->info.getCoerceToType();
-          if (llvm::VectorType *VTy = dyn_cast_or_null<llvm::VectorType>(Ty)) {
-            if (VTy->getBitWidth() > 128) {
-              HasAVXType = true;
-              break;
-            }
-          }
+      for (CallArgList::const_iterator
+             it = args.begin(), ie = args.end(); it != ie; ++it) {
+        if (getABIInfo().isPassedUsingAVXType(it->Ty)) {
+          HasAVXType = true;
+          break;
         }
       }
+
       if (!HasAVXType)
         return true;
     }
 
-    return TargetCodeGenInfo::isNoProtoCallVariadic(FI);
+    return TargetCodeGenInfo::isNoProtoCallVariadic(args, fnType);
   }
 
 };
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index eabc37b..88b4997 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -30,6 +30,7 @@
   class Decl;
 
   namespace CodeGen {
+    class CallArgList;
     class CodeGenModule;
     class CodeGenFunction;
     class CGFunctionInfo;
@@ -161,7 +162,8 @@
     /// same way and some out-of-band information is passed for the
     /// benefit of variadic callees, as is the case for x86-64.
     /// In this case the ABI should be consulted.
-    virtual bool isNoProtoCallVariadic(const CodeGen::CGFunctionInfo &) const;
+    virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args,
+                                       const FunctionNoProtoType *fnType) const;
   };
 }
 
diff --git a/test/CodeGenObjC/variadic-sends.m b/test/CodeGenObjC/variadic-sends.m
index 7e557b0..94d7baf 100644
--- a/test/CodeGenObjC/variadic-sends.m
+++ b/test/CodeGenObjC/variadic-sends.m
@@ -20,8 +20,8 @@
 }
 
 void f2(A *a) {
-  // CHECK-X86-32: call void (i8*, i8*, i32, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, i32, ...)*)
-  // CHECK-X86-64: call void (i8*, i8*, i32, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, i32, ...)*)
+  // CHECK-X86-32: call void (i8*, i8*, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, ...)*)
+  // CHECK-X86-64: call void (i8*, i8*, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, ...)*)
   [a im2: 1, 2];
 }
 
@@ -33,8 +33,8 @@
   [super im1: 1];
 }
 -(void) bar {
-  // CHECK-X86-32: call void (%struct._objc_super*, i8*, i32, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, i32, ...)*)
-  // CHECK-X86-64: call void (%struct._objc_super*, i8*, i32, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, i32, ...)*)
+  // CHECK-X86-32: call void (%struct._objc_super*, i8*, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, ...)*)
+  // CHECK-X86-64: call void (%struct._objc_super*, i8*, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, ...)*)
   [super im2: 1, 2];
 }