diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index e52aed325ab1..a91a34153f94 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -855,11 +855,11 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, llvm::Value *Func = Builder.CreateLoad(FuncPtr); const FunctionType *FuncTy = FnType->castAs(); - 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 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, args.push_back(*i); // Create the function declaration. - const FunctionProtoType *fnType = - cast(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 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { 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 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { 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 @@ generateByrefCopyHelper(CodeGenFunction &CGF, 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 @@ generateByrefDisposeHelper(CodeGenFunction &CGF, 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/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index b5e6e0d7d993..7c08650d278e 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -196,7 +196,8 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor, GlobalDecl(ctor, Ctor_Base))) return; - const CGFunctionInfo &fnInfo = getTypes().getFunctionInfo(ctor, ctorType); + const CGFunctionInfo &fnInfo = + getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType); llvm::Function *fn = cast(GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo)); @@ -218,11 +219,10 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, 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(); - llvm::FunctionType *fnType = - getTypes().GetFunctionType(*fnInfo, proto->isVariadic()); + llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo); return cast(GetOrCreateLLVMFunction(name, fnType, GD, /*ForVTable=*/false)); } @@ -260,7 +260,8 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor, 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(GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo)); @@ -282,11 +283,9 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor, if (llvm::GlobalValue *existing = GetGlobalValue(name)) return existing; - if (!fnInfo) fnInfo = &getTypes().getFunctionInfo(dtor, dtorType); - - llvm::FunctionType *fnType = - getTypes().GetFunctionType(*fnInfo, false); + if (!fnInfo) fnInfo = &getTypes().arrangeCXXDestructor(dtor, dtorType); + llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo); return cast(GetOrCreateLLVMFunction(name, fnType, GD, /*ForVTable=*/false)); } @@ -359,12 +358,10 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall( // -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(MD), - Dtor_Complete); - const FunctionProtoType *FPT = MD->getType()->getAs(); - llvm::Type *Ty - = CGM.getTypes().GetFunctionType(*FInfo, FPT->isVariadic()); + const CGFunctionInfo &FInfo = + CGM.getTypes().arrangeCXXDestructor(cast(MD), + Dtor_Complete); + llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo); llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD); Ty = Ty->getPointerTo()->getPointerTo(); diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index fc3f45d75bf5..befebbecbddb 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -49,9 +49,8 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, MPT->getPointeeType()->getAs(); const CXXRecordDecl *RD = cast(MPT->getClass()->getAs()->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/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6690a69b8d65..2c7a0495aed5 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/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 @@ static CanQualType GetReturnType(QualType RetTy) { return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType(); } +/// Arrange the argument and result information for a value of the +/// given unprototyped function type. const CGFunctionInfo & -CodeGenTypes::getFunctionInfo(CanQual FTNP) { - return getFunctionInfo(FTNP->getResultType().getUnqualifiedType(), - SmallVector(), - FTNP->getExtInfo()); +CodeGenTypes::arrangeFunctionType(CanQual FTNP) { + // When translating an unprototyped function type, always use a + // variadic type. + return arrangeFunctionType(FTNP->getResultType().getUnqualifiedType(), + ArrayRef(), + FTNP->getExtInfo(), + RequiredArgs(0)); } -/// \param Args - contains any initial parameters besides those -/// in the formal type -static const CGFunctionInfo &getFunctionInfo(CodeGenTypes &CGT, - SmallVectorImpl &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 &argTypes, CanQual 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 FTP) { - SmallVector ArgTys; - return ::getFunctionInfo(*this, ArgTys, FTP); +CodeGenTypes::arrangeFunctionType(CanQual FTP) { + SmallVector argTypes; + return ::arrangeFunctionType(*this, argTypes, FTP); } static CallingConv getCallingConventionForDecl(const Decl *D) { @@ -111,82 +122,133 @@ static CallingConv getCallingConventionForDecl(const Decl *D) { return CC_C; } -const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD, - const FunctionProtoType *FTP) { - SmallVector 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 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()); } -const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) { - SmallVector 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(MD) && "wrong method for contructors!"); assert(!isa(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 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 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 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 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 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 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 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(FD)) if (MD->isInstance()) - return getFunctionInfo(MD); + return arrangeCXXMethodDeclaration(MD); CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified(); + assert(isa(FTy)); - if (isa(FTy)) - return getFunctionInfo(FTy.getAs()); + + // When declaring a function without a prototype, always use a + // non-variadic type. + if (isa(FTy)) { + CanQual noProto = FTy.getAs(); + return arrangeFunctionType(noProto->getResultType(), + ArrayRef(), + noProto->getExtInfo(), + RequiredArgs::All); + } + assert(isa(FTy)); - return getFunctionInfo(FTy.getAs()); + return arrangeFunctionType(FTy.getAs()); } -const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) { - SmallVector 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 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 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) { MD->hasAttr()) 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(GD.getDecl()); if (const CXXConstructorDecl *CD = dyn_cast(FD)) - return getFunctionInfo(CD, GD.getCtorType()); + return arrangeCXXConstructorDeclaration(CD, GD.getCtorType()); if (const CXXDestructorDecl *DD = dyn_cast(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(fnType)) { + if (proto->isVariadic()) + required = RequiredArgs(proto->getNumArgs()); + } else if (CGM.getTargetCodeGenInfo() + .isNoProtoCallVariadic(args, cast(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 ArgTys; - for (CallArgList::const_iterator i = Args.begin(), e = Args.end(); + SmallVector 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 ArgTys; - for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); + SmallVector 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 args; - return getFunctionInfo(getContext().VoidTy, args, FunctionType::ExtInfo()); +const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { + return arrangeFunctionType(getContext().VoidTy, ArrayRef(), + FunctionType::ExtInfo(), RequiredArgs::All); } -const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, - const SmallVectorImpl &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 argTypes, + const FunctionType::ExtInfo &info, + RequiredArgs required) { #ifndef NDEBUG - for (SmallVectorImpl::const_iterator - I = ArgTys.begin(), E = ArgTys.end(); I != E; ++I) + for (ArrayRef::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 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, // 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 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 @@ bool CodeGenModule::ReturnTypeUsesFP2Ret(QualType ResultType) { } 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(GD.getDecl())->getType()->getAs()) - 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 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool isVariadic) { 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 @@ llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) { const CGFunctionInfo *Info; if (isa(MD)) - Info = &getFunctionInfo(cast(MD), GD.getDtorType()); + Info = &arrangeCXXDestructor(cast(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/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 24ed366dd860..dead7bd45910 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -98,6 +98,55 @@ namespace CodeGen { SmallVector 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 prototype) { + return forPrototype(prototype.getTypePtr()); + } + + static RequiredArgs forPrototypePlus(CanQual 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 @@ namespace CodeGen { /// 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(this+1); + } + const ArgInfo *getArgsBuffer() const { + return reinterpret_cast(this + 1); + } + + CGFunctionInfo() : Required(RequiredArgs::All) {} public: + static CGFunctionInfo *create(unsigned llvmCC, + const FunctionType::ExtInfo &extInfo, + CanQualType resultType, + ArrayRef 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 @@ namespace CodeGen { 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 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 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::iterator + i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { + i->Profile(ID); } } }; diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 7e94af391f93..7b492fba17af 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1289,7 +1289,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, 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 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, 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 @@ llvm::Value * CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E, const CXXMethodDecl *MD, llvm::Value *This) { - const FunctionProtoType *FPT = MD->getType()->castAs(); - 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 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { // 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/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 2de19840e53d..0ee3fcdae4e5 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1184,7 +1184,7 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { 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(NormalAndEHCleanup, F, &Info, &D); } diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 44acf62aa644..189760821b7a 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -277,7 +277,7 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, 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 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, llvm::Constant **Decls, unsigned NumDecls) { StartFunction(GlobalDecl(), getContext().VoidTy, Fn, - getTypes().getNullaryFunctionInfo(), + getTypes().arrangeNullaryFunction(), FunctionArgList(), SourceLocation()); RunCleanupsScope Scope(*this); @@ -322,7 +322,7 @@ void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, const std::vector > &DtorsAndObjects) { StartFunction(GlobalDecl(), getContext().VoidTy, Fn, - getTypes().getNullaryFunctionInfo(), + getTypes().arrangeNullaryFunction(), FunctionArgList(), SourceLocation()); // Emit the dtors, in reverse order from construction. @@ -350,9 +350,10 @@ CodeGenFunction::generateDestroyHelper(llvm::Constant *addr, 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/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index f67025a32cf0..3871f33a2645 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2454,7 +2454,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, CallArgList Args; EmitCallArgs(Args, dyn_cast(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 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, // 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(FnType) && - !getTargetHooks().isNoProtoCallVariadic(FnInfo)) { - assert(cast(Callee->getType()->getContainedType(0)) - ->isVarArg()); - llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo, false); + if (isa(FnType) && !FnInfo.isVariadic()) { + llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo); CalleeTy = CalleeTy->getPointerTo(); Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast"); } @@ -2678,7 +2676,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { 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/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 47e57032e09a..548bbc9e617e 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -33,8 +33,6 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, assert(MD->isInstance() && "Trying to emit a member call expr on a static method!"); - const FunctionProtoType *FPT = MD->getType()->getAs(); - CallArgList Args; // Push the this ptr. @@ -45,13 +43,16 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, QualType T = getContext().getPointerType(getContext().VoidPtrTy); Args.add(RValue::get(VTT), T); } + + const FunctionProtoType *FPT = MD->getType()->castAs(); + 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 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, // Compute the function type we're calling. const CGFunctionInfo *FInfo = 0; if (isa(MD)) - FInfo = &CGM.getTypes().getFunctionInfo(cast(MD), - Dtor_Complete); + FInfo = &CGM.getTypes().arrangeCXXDestructor(cast(MD), + Dtor_Complete); else if (isa(MD)) - FInfo = &CGM.getTypes().getFunctionInfo(cast(MD), - Ctor_Complete); + FInfo = &CGM.getTypes().arrangeCXXConstructorDeclaration( + cast(MD), + Ctor_Complete); else - FInfo = &CGM.getTypes().getFunctionInfo(MD); + FInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(MD); - const FunctionProtoType *FPT = MD->getType()->getAs(); - 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 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, // 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 @@ namespace { 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 @@ namespace { } // 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 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // 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 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, 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 @@ static void EmitObjectDelete(CodeGenFunction &CGF, } 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 @@ namespace { } // 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/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 94bad921809d..9792017a062d 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -307,7 +307,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, 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 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, 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 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF, 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 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, // 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 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD, 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 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF, 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 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, 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 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ 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::EmitObjCAutoreleasePoolStmt( 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 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( 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 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( 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/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 50ab7d2e385b..3e8b528c77f6 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -103,8 +103,6 @@ class LazyRuntimeFunction { /// 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 @@ static std::string SymbolNameForMethod(const StringRef &ClassName, 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 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, 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 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, 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 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, 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 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, }; 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 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, 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 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, // 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 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, 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/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index b4896920b49c..d42f9f27fa30 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -241,9 +241,9 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: SmallVector 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 @@ public: }; protected: - CodeGen::CodeGenModule &CGM; llvm::LLVMContext &VMContext; // FIXME! May not be needing this after all. unsigned ObjCABI; @@ -904,7 +903,7 @@ protected: 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 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, 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 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, 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 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, } } - 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 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, 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 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, 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 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, // 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 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, 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/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index df039bb0ffb6..17557cf103e2 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -327,3 +327,48 @@ void CGObjCRuntime::EmitAtSynchronizedStmt(CodeGenFunction &CGF, // 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/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 39523c98a611..0f3cb549ec77 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -63,6 +63,9 @@ namespace CodeGen { /// 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 @@ public: 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/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index c5383b670450..77e9fb3ca84c 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -242,8 +242,8 @@ void CodeGenFunction::GenerateVarArgsThunk( 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(Callee); @@ -351,13 +351,13 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, // 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 CodeGenFunction::GenerateThunk(llvm::Function *Fn, 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/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index dd613b4014f9..c30fe22a6744 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -66,7 +66,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, : 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 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, const FunctionDecl *FD = cast(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 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { const FunctionDecl *D = cast(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()) - 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/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 16ca7ec80d0a..03465199a061 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/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 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { // The function type can be built; call the appropriate routines to // build it. const CGFunctionInfo *FI; - bool isVariadic; if (const FunctionProtoType *FPT = dyn_cast(FT)) { - FI = &getFunctionInfo( + FI = &arrangeFunctionType( CanQual::CreateUnsafe(QualType(FPT, 0))); - isVariadic = FPT->isVariadic(); } else { const FunctionNoProtoType *FNPT = cast(FT); - FI = &getFunctionInfo( + FI = &arrangeFunctionType( CanQual::CreateUnsafe(QualType(FNPT, 0))); - isVariadic = true; } // If there is something higher level prodding our CGFunctionInfo, then @@ -494,7 +493,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { } 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/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index 7f0f8ac5f0c5..ba2b3ae54902 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -52,10 +52,13 @@ namespace clang { 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 @@ class CodeGenTypes { 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 @@ private: llvm::DenseMap 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 @@ public: 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 @@ public: /// 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 Ty); - const CGFunctionInfo &getFunctionInfo(CanQual 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 Ty); + const CGFunctionInfo &arrangeFunctionType(CanQual 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 &ArgTys, - const FunctionType::ExtInfo &Info); + /// \param argTypes - must all actually be canonical as params + const CGFunctionInfo &arrangeFunctionType(CanQualType returnType, + ArrayRef 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/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 8d06b6011c01..68f2f1df7256 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -218,8 +218,8 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, cast(MPT->getClass()->getAs()->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 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, // 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/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index cae8f5fb1a0f..2ee662c1e70b 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -98,8 +98,8 @@ unsigned TargetCodeGenInfo::getSizeOfUnwindException() const { 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 @@ public: 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(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 @@ public: X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX) : TargetCodeGenInfo(new X86_64ABIInfo(CGT, HasAVX)) {} + const X86_64ABIInfo &getABIInfo() const { + return static_cast(TargetCodeGenInfo::getABIInfo()); + } + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { return 7; } @@ -980,33 +995,29 @@ public: 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(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/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index eabc37b464e3..88b4997d48cc 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -30,6 +30,7 @@ namespace clang { class Decl; namespace CodeGen { + class CallArgList; class CodeGenModule; class CodeGenFunction; class CGFunctionInfo; @@ -161,7 +162,8 @@ namespace clang { /// 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/clang/test/CodeGenObjC/variadic-sends.m b/clang/test/CodeGenObjC/variadic-sends.m index 7e557b0178d8..94d7bafba472 100644 --- a/clang/test/CodeGenObjC/variadic-sends.m +++ b/clang/test/CodeGenObjC/variadic-sends.m @@ -20,8 +20,8 @@ void f1(A *a) { } 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 @@ void f2(A *a) { [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]; }