@@ -778,6 +778,86 @@ void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
778778 s->getStmtClassName ());
779779}
780780
781+ void CIRGenFunction::emitForwardingCallToLambda (
782+ const CXXMethodDecl *callOperator, CallArgList &callArgs) {
783+ // Get the address of the call operator.
784+ const CIRGenFunctionInfo &calleeFnInfo =
785+ cgm.getTypes ().arrangeCXXMethodDeclaration (callOperator);
786+ cir::FuncOp calleePtr = cgm.getAddrOfFunction (
787+ GlobalDecl (callOperator), cgm.getTypes ().getFunctionType (calleeFnInfo));
788+
789+ // Prepare the return slot.
790+ const FunctionProtoType *fpt =
791+ callOperator->getType ()->castAs <FunctionProtoType>();
792+ QualType resultType = fpt->getReturnType ();
793+ ReturnValueSlot returnSlot;
794+
795+ // We don't need to separately arrange the call arguments because
796+ // the call can't be variadic anyway --- it's impossible to forward
797+ // variadic arguments.
798+
799+ // Now emit our call.
800+ CIRGenCallee callee =
801+ CIRGenCallee::forDirect (calleePtr, GlobalDecl (callOperator));
802+ RValue rv = emitCall (calleeFnInfo, callee, returnSlot, callArgs);
803+
804+ // If necessary, copy the returned value into the slot.
805+ if (!resultType->isVoidType () && returnSlot.isNull ()) {
806+ if (getLangOpts ().ObjCAutoRefCount && resultType->isObjCRetainableType ())
807+ cgm.errorNYI (callOperator->getSourceRange (),
808+ " emitForwardingCallToLambda: ObjCAutoRefCount" );
809+ emitReturnOfRValue (*currSrcLoc, rv, resultType);
810+ } else {
811+ cgm.errorNYI (callOperator->getSourceRange (),
812+ " emitForwardingCallToLambda: return slot is not null" );
813+ }
814+ }
815+
816+ void CIRGenFunction::emitLambdaDelegatingInvokeBody (const CXXMethodDecl *md) {
817+ const CXXRecordDecl *lambda = md->getParent ();
818+
819+ // Start building arguments for forwarding call
820+ CallArgList callArgs;
821+
822+ QualType lambdaType = getContext ().getCanonicalTagType (lambda);
823+ QualType thisType = getContext ().getPointerType (lambdaType);
824+ Address thisPtr =
825+ createMemTemp (lambdaType, getLoc (md->getSourceRange ()), " unused.capture" );
826+ callArgs.add (RValue::get (thisPtr.getPointer ()), thisType);
827+
828+ // Add the rest of the parameters.
829+ for (auto *param : md->parameters ())
830+ emitDelegateCallArg (callArgs, param, param->getBeginLoc ());
831+
832+ const CXXMethodDecl *callOp = lambda->getLambdaCallOperator ();
833+ // For a generic lambda, find the corresponding call operator specialization
834+ // to which the call to the static-invoker shall be forwarded.
835+ if (lambda->isGenericLambda ()) {
836+ assert (md->isFunctionTemplateSpecialization ());
837+ const TemplateArgumentList *tal = md->getTemplateSpecializationArgs ();
838+ FunctionTemplateDecl *callOpTemplate =
839+ callOp->getDescribedFunctionTemplate ();
840+ void *InsertPos = nullptr ;
841+ FunctionDecl *correspondingCallOpSpecialization =
842+ callOpTemplate->findSpecialization (tal->asArray (), InsertPos);
843+ assert (correspondingCallOpSpecialization);
844+ callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);
845+ }
846+ emitForwardingCallToLambda (callOp, callArgs);
847+ }
848+
849+ void CIRGenFunction::emitLambdaStaticInvokeBody (const CXXMethodDecl *md) {
850+ if (md->isVariadic ()) {
851+ // Codgen for LLVM doesn't emit code for this as well, it says:
852+ // FIXME: Making this work correctly is nasty because it requires either
853+ // cloning the body of the call operator or making the call operator
854+ // forward.
855+ cgm.errorNYI (md->getSourceRange (), " emitLambdaStaticInvokeBody: variadic" );
856+ }
857+
858+ emitLambdaDelegatingInvokeBody (md);
859+ }
860+
781861void CIRGenFunction::destroyCXXObject (CIRGenFunction &cgf, Address addr,
782862 QualType type) {
783863 const auto *record = type->castAsCXXRecordDecl ();
0 commit comments