From e56bb36e8eea89bae7dfe6eb6ea0455af126bf4a Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 7 Dec 2012 07:03:17 +0000 Subject: Fix the required args count for variadic blocks. We were emitting calls to blocks as if all arguments were required --- i.e. with signature (A,B,C,D,...) rather than (A,B,...). This patch fixes that and accounts for the implicit block-context argument as a required argument. In addition, this patch changes the function type under which we call unprototyped functions on platforms like x86-64 that guarantee compatibility of variadic functions with unprototyped function types; previously we would always call such functions under the LLVM type T (...)*, but now we will call them under the type T (A,B,C,D,...)*. This last change should have no material effect except for making the type conventions more explicit; it was a side-effect of the most convenient implementation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169588 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 59 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 12 deletions(-) (limited to 'lib/CodeGen/CGCall.cpp') diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 5effa0ccd5..1047931b60 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -316,6 +316,37 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) { return arrangeFunctionDeclaration(FD); } +/// Arrange a call as unto a free function, except possibly with an +/// additional number of formal parameters considered required. +static const CGFunctionInfo & +arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, + const CallArgList &args, + const FunctionType *fnType, + unsigned numExtraRequiredArgs) { + assert(args.size() >= numExtraRequiredArgs); + + // In most cases, there are no optional arguments. + RequiredArgs required = RequiredArgs::All; + + // If we have a variadic prototype, the required arguments are the + // extra prefix plus the arguments in the prototype. + if (const FunctionProtoType *proto = dyn_cast(fnType)) { + if (proto->isVariadic()) + required = RequiredArgs(proto->getNumArgs() + numExtraRequiredArgs); + + // If we don't have a prototype at all, but we're supposed to + // explicitly use the variadic convention for unprototyped calls, + // treat all of the arguments as required but preserve the nominal + // possibility of variadics. + } else if (CGT.CGM.getTargetCodeGenInfo() + .isNoProtoCallVariadic(args, cast(fnType))) { + required = RequiredArgs(args.size()); + } + + return CGT.arrangeFreeFunctionCall(fnType->getResultType(), args, + fnType->getExtInfo(), required); +} + /// 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 @@ -323,17 +354,15 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) { const CGFunctionInfo & CodeGenTypes::arrangeFreeFunctionCall(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 arrangeFreeFunctionLikeCall(*this, args, fnType, 0); +} - return arrangeFreeFunctionCall(fnType->getResultType(), args, - fnType->getExtInfo(), required); +/// A block function call is essentially a free-function call with an +/// extra implicit argument. +const CGFunctionInfo & +CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args, + const FunctionType *fnType) { + return arrangeFreeFunctionLikeCall(*this, args, fnType, 1); } const CGFunctionInfo & @@ -865,8 +894,14 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { break; } - for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), - ie = FI.arg_end(); it != ie; ++it) { + // Add in all of the required arguments. + CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), ie; + if (FI.isVariadic()) { + ie = it + FI.getRequiredArgs().getNumRequiredArgs(); + } else { + ie = FI.arg_end(); + } + for (; it != ie; ++it) { const ABIArgInfo &argAI = it->info; // Insert a padding type to ensure proper alignment. -- cgit v1.2.3-70-g09d2