[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