[cfe-commits] r150660 - in /cfe/trunk/lib/CodeGen: CGClass.cpp CodeGenFunction.h
Douglas Gregor
dgregor at apple.com
Thu Feb 16 19:08:20 PST 2012
On Feb 15, 2012, at 8:26 PM, Eli Friedman wrote:
> On Wed, Feb 15, 2012 at 7:47 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
>> Author: efriedma
>> Date: Wed Feb 15 21:47:28 2012
>> New Revision: 150660
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=150660&view=rev
>> Log:
>> Initial implementation of IRGen for the lambda conversion-to-function-pointer operator.
>>
>>
>> Modified:
>> cfe/trunk/lib/CodeGen/CGClass.cpp
>> cfe/trunk/lib/CodeGen/CodeGenFunction.h
>>
>> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=150660&r1=150659&r2=150660&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Feb 15 21:47:28 2012
>> @@ -1725,6 +1725,98 @@
>> CGM.ErrorUnsupported(CurFuncDecl, "lambda conversion to block");
>> }
>>
>> +void CodeGenFunction::EmitLambdaThunkBody(llvm::Function *Fn,
>> + const CGFunctionInfo &FnInfo,
>> + const CXXRecordDecl *Lambda) {
>> + DeclarationName Name
>> + = getContext().DeclarationNames.getCXXOperatorName(OO_Call);
>> + DeclContext::lookup_const_result Calls = Lambda->lookup(Name);
>> + CXXMethodDecl *MD = 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;
>> +
>> + 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(MD);
>> + const CGFunctionInfo &CalleeFnInfo = CGM.getTypes().getFunctionInfo(GD);
>> + llvm::Type *Ty =
>> + CGM.getTypes().GetFunctionType(CalleeFnInfo, FPT->isVariadic());
>> + llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
>> +
>> + // Determine whether we have a return value slot to use.
>> + ReturnValueSlot Slot;
>> + if (!ResultType->isVoidType() &&
>> + FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
>> + hasAggregateLLVMType(CurFnInfo->getReturnType()))
>> + Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
>> +
>> + // Now emit our call.
>> + RValue RV = EmitCall(CalleeFnInfo, Callee, Slot, CallArgs, MD);
>> +
>> + // 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()) {
>> + // 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...
>
> Thinking about this a bit more, it's probably not such a good idea to
> make the conversion constexpr because there would be ABI implications.
> But having the returned function in the AST would be convenient for
> mangling, it would reduce the amount of magic in IRGen, and it would
> make constant folding the conversion a bit more straightforward.
> Doug, any opinion?
FYI, I've gone ahead and made the __invoke function part of the AST in r150783.
- Doug
More information about the cfe-commits
mailing list