[cfe-commits] r150660 - in /cfe/trunk/lib/CodeGen: CGClass.cpp CodeGenFunction.h

Eli Friedman eli.friedman at gmail.com
Wed Feb 15 20:26:42 PST 2012


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?

-Eli




More information about the cfe-commits mailing list