summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp59
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp16
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h7
3 files changed, 20 insertions, 62 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index ed44679a886..7e94af391f9 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/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);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 1034de736c1..28c5935de04 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -448,13 +448,15 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
FD->hasAttr<CUDAGlobalAttr>())
CGM.getCUDARuntime().EmitDeviceStubBody(*this, Args);
else if (isa<CXXConversionDecl>(FD) &&
- cast<CXXConversionDecl>(FD)->getParent()->isLambda()) {
- // The lambda conversion operators are special; the semantics can't be
- // expressed in the AST, so IRGen needs to special-case them.
- if (cast<CXXConversionDecl>(FD)->isLambdaToBlockPointerConversion())
- EmitLambdaToBlockPointerBody(Args);
- else
- EmitLambdaToFunctionPointerBody(Args);
+ cast<CXXConversionDecl>(FD)->isLambdaToBlockPointerConversion()) {
+ // The lambda conversion to block pointer is special; the semantics can't be
+ // expressed in the AST, so IRGen needs to special-case it.
+ EmitLambdaToBlockPointerBody(Args);
+ } else if (isa<CXXMethodDecl>(FD) &&
+ cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
+ // The lambda "__invoke" function is special, because it forwards or
+ // clones the body of the function call operator (but is actually static).
+ EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));
}
else
EmitFunctionBody(Args);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 2b9b8ab7b88..427ee08e69e 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1377,11 +1377,8 @@ public:
void EmitFunctionBody(FunctionArgList &Args);
void EmitLambdaToBlockPointerBody(FunctionArgList &Args);
- void EmitLambdaToFunctionPointerBody(FunctionArgList &Args);
- llvm::Constant *EmitLambdaConvertedFnPtr(const CXXMethodDecl *MD);
- void EmitLambdaThunkBody(llvm::Function *Fn,
- const CGFunctionInfo &FnInfo,
- const CXXRecordDecl *Lambda);
+ void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
+ void EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD);
/// EmitReturnBlock - Emit the unified return block, trying to avoid its
/// emission when possible.
OpenPOWER on IntegriCloud