aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2012-12-07 07:03:17 +0000
committerJohn McCall <rjmccall@apple.com>2012-12-07 07:03:17 +0000
commite56bb36e8eea89bae7dfe6eb6ea0455af126bf4a (patch)
treec6ac1420506da704a1f788684944e958214e818e /lib/CodeGen/CGCall.cpp
parent8fda1ab0fbfeac24489906d0bd6714c337f66e0f (diff)
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
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r--lib/CodeGen/CGCall.cpp59
1 files changed, 47 insertions, 12 deletions
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<FunctionProtoType>(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<FunctionNoProtoType>(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<FunctionProtoType>(fnType)) {
- if (proto->isVariadic())
- required = RequiredArgs(proto->getNumArgs());
- } else if (CGM.getTargetCodeGenInfo()
- .isNoProtoCallVariadic(args, cast<FunctionNoProtoType>(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.