diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-02-25 02:48:22 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-02-25 02:48:22 +0000 |
commit | 64bee65a3436e3f0c352fcfe2130676f3502cffe (patch) | |
tree | 9154d934a177c762072a49a0fa5d0813c37c780a /lib/CodeGen/CGClass.cpp | |
parent | e1d4330adaaa7faf093e725c9c993207eb2d778a (diff) |
Work-in-progress for lambda conversion-to-block operator. Still need to implement the retain+autorelease outside of ARC, and there's a bug that causes the generated code to crash in ARC (which I think is unrelated to my code, although I'm not completely sure).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151428 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 83 |
1 files changed, 62 insertions, 21 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 2cea434f62..618a3f86cd 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "CGBlocks.h" #include "CGDebugInfo.h" #include "CodeGenFunction.h" #include "clang/AST/CXXInheritance.h" @@ -1726,33 +1727,17 @@ CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E, return CGM.GetAddrOfFunction(MD, fnType); } -void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) { - CGM.ErrorUnsupported(CurFuncDecl, "lambda conversion to block"); -} - -void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { - const CXXRecordDecl *Lambda = MD->getParent(); +void CodeGenFunction::EmitForwardingCallToLambda(const CXXRecordDecl *Lambda, + CallArgList &CallArgs) { + // Lookup the call operator DeclarationName Name = getContext().DeclarationNames.getCXXOperatorName(OO_Call); DeclContext::lookup_const_result Calls = Lambda->lookup(Name); CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(*Calls.first++); - const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *FPT = + CallOperator->getType()->getAs<FunctionProtoType>(); QualType ResultType = FPT->getResultType(); - // Start building arguments for forwarding call - CallArgList CallArgs; - - QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); - llvm::Value *ThisPtr = llvm::UndefValue::get(getTypes().ConvertType(ThisType)); - CallArgs.add(RValue::get(ThisPtr), ThisType); - - // Add the rest of the parameters. - for (FunctionDecl::param_const_iterator I = MD->param_begin(), - E = MD->param_end(); I != E; ++I) { - ParmVarDecl *param = *I; - EmitDelegateCallArg(CallArgs, param); - } - // Get the address of the call operator. GlobalDecl GD(CallOperator); const CGFunctionInfo &CalleeFnInfo = @@ -1776,11 +1761,67 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { EmitReturnOfRValue(RV, ResultType); } +void CodeGenFunction::EmitLambdaBlockInvokeBody() { + const BlockDecl *BD = BlockInfo->getBlockDecl(); + const VarDecl *variable = BD->capture_begin()->getVariable(); + const CXXRecordDecl *Lambda = variable->getType()->getAsCXXRecordDecl(); + + // Start building arguments for forwarding call + CallArgList CallArgs; + + QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); + llvm::Value *ThisPtr = GetAddrOfBlockDecl(variable, false); + CallArgs.add(RValue::get(ThisPtr), ThisType); + + // Add the rest of the parameters. + for (BlockDecl::param_const_iterator I = BD->param_begin(), + E = BD->param_end(); I != E; ++I) { + ParmVarDecl *param = *I; + EmitDelegateCallArg(CallArgs, param); + } + + EmitForwardingCallToLambda(Lambda, CallArgs); +} + +void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) { + if (cast<CXXMethodDecl>(CurFuncDecl)->isVariadic()) { + // FIXME: Making this work correctly is nasty because it requires either + // cloning the body of the call operator or making the call operator forward. + CGM.ErrorUnsupported(CurFuncDecl, "lambda conversion to variadic function"); + return; + } + + InLambdaConversionToBlock = true; + EmitFunctionBody(Args); + InLambdaConversionToBlock = false; +} + +void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { + const CXXRecordDecl *Lambda = MD->getParent(); + + // Start building arguments for forwarding call + CallArgList CallArgs; + + QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); + llvm::Value *ThisPtr = llvm::UndefValue::get(getTypes().ConvertType(ThisType)); + CallArgs.add(RValue::get(ThisPtr), ThisType); + + // Add the rest of the parameters. + for (FunctionDecl::param_const_iterator I = MD->param_begin(), + E = MD->param_end(); I != E; ++I) { + ParmVarDecl *param = *I; + EmitDelegateCallArg(CallArgs, param); + } + + EmitForwardingCallToLambda(Lambda, CallArgs); +} + void CodeGenFunction::EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD) { if (MD->isVariadic()) { // FIXME: Making this work correctly is nasty because it requires either // cloning the body of the call operator or making the call operator forward. CGM.ErrorUnsupported(MD, "lambda conversion to variadic function"); + return; } EmitLambdaDelegatingInvokeBody(MD); |