aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGClass.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-17 03:02:34 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-17 03:02:34 +0000
commit27dd7d962bbf774988bc5e59d04a7743ed503514 (patch)
treee26142ffbfa9e462cf1800ab500b902bd5437b22 /lib/CodeGen/CGClass.cpp
parent92dc03546ccfd417108c1fc74321091a82cbeeee (diff)
Rework the Sema/AST/IRgen dance for the lambda closure type's
conversion to function pointer. Rather than having IRgen synthesize the body of this function, we instead introduce a static member function "__invoke" with the same signature as the lambda's operator() in the AST. Sema then generates a body for the conversion to function pointer which simply returns the address of __invoke. This approach makes it easier to evaluate a call to the conversion function as a constant, makes the linkage of the __invoke function follow the normal rules for member functions, and may make life easier down the road if we ever want to constexpr'ify some of lambdas. Note that IR generation is responsible for filling in the body of __invoke (Sema just adds a dummy body), because the body can't generally be expressed in C++. Eli, please review! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150783 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r--lib/CodeGen/CGClass.cpp59
1 files changed, 9 insertions, 50 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index ed44679a88..7e94af391f 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1725,26 +1725,15 @@ void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
CGM.ErrorUnsupported(CurFuncDecl, "lambda conversion to block");
}
-void CodeGenFunction::EmitLambdaThunkBody(llvm::Function *Fn,
- const CGFunctionInfo &FnInfo,
- const CXXRecordDecl *Lambda) {
+void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
+ const CXXRecordDecl *Lambda = MD->getParent();
DeclarationName Name
= getContext().DeclarationNames.getCXXOperatorName(OO_Call);
DeclContext::lookup_const_result Calls = Lambda->lookup(Name);
- CXXMethodDecl *MD = cast<CXXMethodDecl>(*Calls.first++);
+ CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(*Calls.first++);
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
QualType ResultType = FPT->getResultType();
- // Begin function
- FunctionArgList FunctionArgs;
- for (FunctionDecl::param_const_iterator I = MD->param_begin(),
- E = MD->param_end(); I != E; ++I) {
- ParmVarDecl *Param = *I;
- FunctionArgs.push_back(Param);
- }
- StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs,
- SourceLocation());
-
// Start building arguments for forwarding call
CallArgList CallArgs;
@@ -1760,7 +1749,7 @@ void CodeGenFunction::EmitLambdaThunkBody(llvm::Function *Fn,
}
// Get the address of the call operator.
- GlobalDecl GD(MD);
+ GlobalDecl GD(CallOperator);
const CGFunctionInfo &CalleeFnInfo = CGM.getTypes().getFunctionInfo(GD);
llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CalleeFnInfo, FPT->isVariadic());
@@ -1769,54 +1758,24 @@ void CodeGenFunction::EmitLambdaThunkBody(llvm::Function *Fn,
// Determine whether we have a return value slot to use.
ReturnValueSlot Slot;
if (!ResultType->isVoidType() &&
- FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+ CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
hasAggregateLLVMType(CurFnInfo->getReturnType()))
Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
// Now emit our call.
- RValue RV = EmitCall(CalleeFnInfo, Callee, Slot, CallArgs, MD);
+ RValue RV = EmitCall(CalleeFnInfo, Callee, Slot, CallArgs, CallOperator);
// Forward the returned value
if (!ResultType->isVoidType() && Slot.isNull())
EmitReturnOfRValue(RV, ResultType);
-
- // End the function.
- FinishFunction();
}
-llvm::Constant *
-CodeGenFunction::EmitLambdaConvertedFnPtr(const CXXMethodDecl *MD) {
- QualType FnTy = MD->getResultType()->getPointeeType();
- CanQual<FunctionProtoType> CanFnTy =
- CGM.getContext().getCanonicalType(FnTy)->getAs<FunctionProtoType>();
- llvm::FunctionType *FnLLVMTy = cast<llvm::FunctionType>(CGM.getTypes().ConvertType(FnTy));
- const CXXRecordDecl *Lambda = MD->getParent();
- const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(CanFnTy);
-
- if (CanFnTy->isVariadic()) {
+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 llvm::UndefValue::get(FnLLVMTy->getPointerTo());
}
- // Build a declaration for the function which this function will
- // return a pointer to.
- // FIXME: Should the "thunk" actually be part of the AST? That would allow
- // the conversion to function pointer to be constexpr...
- std::string MangledName =
- (llvm::Twine(CurFn->getName()) + "_lambdacallthunk").str();
- llvm::Function *Fn =
- llvm::Function::Create(FnLLVMTy, llvm::Function::InternalLinkage,
- MangledName, &CGM.getModule());
-
- // Emit the definition of the new function.
- CodeGenFunction(CGM).EmitLambdaThunkBody(Fn, FnInfo, Lambda);
- return Fn;
-}
-
-void CodeGenFunction::EmitLambdaToFunctionPointerBody(FunctionArgList &Args) {
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurFuncDecl);
- EmitReturnOfRValue(RValue::get(EmitLambdaConvertedFnPtr(MD)),
- MD->getResultType());
+ EmitLambdaDelegatingInvokeBody(MD);
}