Author: Amy Huang Date: 2023-06-22T11:42:33-07:00 New Revision: 8ed7aa59f489715d39d32e72a787b8e75cfda151
URL: https://github.com/llvm/llvm-project/commit/8ed7aa59f489715d39d32e72a787b8e75cfda151 DIFF: https://github.com/llvm/llvm-project/commit/8ed7aa59f489715d39d32e72a787b8e75cfda151.diff LOG: Revert "Try to implement lambdas with inalloca parameters by forwarding without use of inallocas." Causes a clang crash (see crbug.com/1457256). This reverts commit 015049338d7e8e0e81f2ad2f94e5a43e2e3f5220. Added: Modified: clang/include/clang/CodeGen/CGFunctionInfo.h clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGCall.h clang/lib/CodeGen/CGClass.cpp clang/lib/CodeGen/CGDeclCXX.cpp clang/lib/CodeGen/CodeGenABITypes.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/CodeGen/CodeGenTypes.h clang/lib/CodeGen/Targets/X86.cpp clang/test/CodeGenCXX/inalloca-lambda.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h index b8971d5793f36..39c7a578c8c4e 100644 --- a/clang/include/clang/CodeGen/CGFunctionInfo.h +++ b/clang/include/clang/CodeGen/CGFunctionInfo.h @@ -567,10 +567,6 @@ class CGFunctionInfo final /// Whether this is a chain call. unsigned ChainCall : 1; - /// Whether this function is called by forwarding arguments. - /// This doesn't support inalloca or varargs. - unsigned DelegateCall : 1; - /// Whether this function is a CMSE nonsecure call unsigned CmseNSCall : 1; @@ -620,11 +616,14 @@ class CGFunctionInfo final CGFunctionInfo() : Required(RequiredArgs::All) {} public: - static CGFunctionInfo * - create(unsigned llvmCC, bool instanceMethod, bool chainCall, - bool delegateCall, const FunctionType::ExtInfo &extInfo, - ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, - ArrayRef<CanQualType> argTypes, RequiredArgs required); + static CGFunctionInfo *create(unsigned llvmCC, + bool instanceMethod, + bool chainCall, + const FunctionType::ExtInfo &extInfo, + ArrayRef<ExtParameterInfo> paramInfos, + CanQualType resultType, + ArrayRef<CanQualType> argTypes, + RequiredArgs required); void operator delete(void *p) { ::operator delete(p); } // Friending class TrailingObjects is apparently not good enough for MSVC, @@ -664,8 +663,6 @@ class CGFunctionInfo final bool isChainCall() const { return ChainCall; } - bool isDelegateCall() const { return DelegateCall; } - bool isCmseNSCall() const { return CmseNSCall; } bool isNoReturn() const { return NoReturn; } @@ -752,7 +749,6 @@ class CGFunctionInfo final ID.AddInteger(getASTCallingConvention()); ID.AddBoolean(InstanceMethod); ID.AddBoolean(ChainCall); - ID.AddBoolean(DelegateCall); ID.AddBoolean(NoReturn); ID.AddBoolean(ReturnsRetained); ID.AddBoolean(NoCallerSavedRegs); @@ -770,16 +766,17 @@ class CGFunctionInfo final for (const auto &I : arguments()) I.type.Profile(ID); } - static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod, - bool ChainCall, bool IsDelegateCall, + static void Profile(llvm::FoldingSetNodeID &ID, + bool InstanceMethod, + bool ChainCall, const FunctionType::ExtInfo &info, ArrayRef<ExtParameterInfo> paramInfos, - RequiredArgs required, CanQualType resultType, + RequiredArgs required, + CanQualType resultType, ArrayRef<CanQualType> argTypes) { ID.AddInteger(info.getCC()); ID.AddBoolean(InstanceMethod); ID.AddBoolean(ChainCall); - ID.AddBoolean(IsDelegateCall); ID.AddBoolean(info.getNoReturn()); ID.AddBoolean(info.getProducesResult()); ID.AddBoolean(info.getNoCallerSavedRegs()); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a9af9916b8c70..61029c9226d7b 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -111,7 +111,8 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) { // When translating an unprototyped function type, always use a // variadic type. return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(), - FnInfoOpts::None, std::nullopt, + /*instanceMethod=*/false, + /*chainCall=*/false, std::nullopt, FTNP->getExtInfo(), {}, RequiredArgs(0)); } @@ -187,10 +188,10 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, appendParameterTypes(CGT, prefix, paramInfos, FTP); CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); - FnInfoOpts opts = - instanceMethod ? FnInfoOpts::IsInstanceMethod : FnInfoOpts::None; - return CGT.arrangeLLVMFunctionInfo(resultType, opts, prefix, - FTP->getExtInfo(), paramInfos, Required); + return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, + /*chainCall=*/false, prefix, + FTP->getExtInfo(), paramInfos, + Required); } /// Arrange the argument and result information for a value of the @@ -269,7 +270,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, argTypes.push_back(DeriveThisType(RD, MD)); return ::arrangeLLVMFunctionInfo( - *this, /*instanceMethod=*/true, argTypes, + *this, true, argTypes, FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>()); } @@ -361,8 +362,9 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) { : TheCXXABI.hasMostDerivedReturn(GD) ? CGM.getContext().VoidPtrTy : Context.VoidTy; - return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::IsInstanceMethod, - argTypes, extInfo, paramInfos, required); + return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true, + /*chainCall=*/false, argTypes, extInfo, + paramInfos, required); } static SmallVector<CanQualType, 16> @@ -436,9 +438,9 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs, ArgTypes.size()); } - - return arrangeLLVMFunctionInfo(ResultType, FnInfoOpts::IsInstanceMethod, - ArgTypes, Info, ParamInfos, Required); + return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true, + /*chainCall=*/false, ArgTypes, Info, + ParamInfos, Required); } /// Arrange the argument and result information for the declaration or @@ -457,9 +459,10 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { // When declaring a function without a prototype, always use a // non-variadic type. if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) { - return arrangeLLVMFunctionInfo(noProto->getReturnType(), FnInfoOpts::None, - std::nullopt, noProto->getExtInfo(), {}, - RequiredArgs::All); + return arrangeLLVMFunctionInfo( + noProto->getReturnType(), /*instanceMethod=*/false, + /*chainCall=*/false, std::nullopt, noProto->getExtInfo(), {}, + RequiredArgs::All); } return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>()); @@ -508,9 +511,9 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, RequiredArgs required = (MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All); - return arrangeLLVMFunctionInfo(GetReturnType(MD->getReturnType()), - FnInfoOpts::None, argTys, einfo, extParamInfos, - required); + return arrangeLLVMFunctionInfo( + GetReturnType(MD->getReturnType()), /*instanceMethod=*/false, + /*chainCall=*/false, argTys, einfo, extParamInfos, required); } const CGFunctionInfo & @@ -519,8 +522,9 @@ CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType, auto argTypes = getArgTypesForCall(Context, args); FunctionType::ExtInfo einfo; - return arrangeLLVMFunctionInfo(GetReturnType(returnType), FnInfoOpts::None, - argTypes, einfo, {}, RequiredArgs::All); + return arrangeLLVMFunctionInfo( + GetReturnType(returnType), /*instanceMethod=*/false, + /*chainCall=*/false, argTypes, einfo, {}, RequiredArgs::All); } const CGFunctionInfo & @@ -545,7 +549,8 @@ CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) { assert(MD->isVirtual() && "only methods have thunks"); CanQual<FunctionProtoType> FTP = GetFormalType(MD); CanQualType ArgTys[] = {DeriveThisType(MD->getParent(), MD)}; - return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::None, ArgTys, + return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false, + /*chainCall=*/false, ArgTys, FTP->getExtInfo(), {}, RequiredArgs(1)); } @@ -564,8 +569,9 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD, ArgTys.push_back(Context.IntTy); CallingConv CC = Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true); - return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::IsInstanceMethod, - ArgTys, FunctionType::ExtInfo(CC), {}, + return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true, + /*chainCall=*/false, ArgTys, + FunctionType::ExtInfo(CC), {}, RequiredArgs::All); } @@ -609,10 +615,10 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, SmallVector<CanQualType, 16> argTypes; for (const auto &arg : args) argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty)); - FnInfoOpts opts = chainCall ? FnInfoOpts::IsChainCall : FnInfoOpts::None; return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), - opts, argTypes, fnType->getExtInfo(), - paramInfos, required); + /*instanceMethod=*/false, chainCall, + argTypes, fnType->getExtInfo(), paramInfos, + required); } /// Figure out the rules for calling a function with the given formal @@ -643,8 +649,8 @@ CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto, auto argTypes = getArgTypesForDeclaration(Context, params); return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()), - FnInfoOpts::None, argTypes, - proto->getExtInfo(), paramInfos, + /*instanceMethod*/ false, /*chainCall*/ false, + argTypes, proto->getExtInfo(), paramInfos, RequiredArgs::forPrototypePlus(proto, 1)); } @@ -655,9 +661,10 @@ CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType, SmallVector<CanQualType, 16> argTypes; for (const auto &Arg : args) argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); - return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None, - argTypes, FunctionType::ExtInfo(), - /*paramInfos=*/{}, RequiredArgs::All); + return arrangeLLVMFunctionInfo( + GetReturnType(resultType), /*instanceMethod=*/false, + /*chainCall=*/false, argTypes, FunctionType::ExtInfo(), + /*paramInfos=*/ {}, RequiredArgs::All); } const CGFunctionInfo & @@ -665,17 +672,17 @@ CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args) { auto argTypes = getArgTypesForDeclaration(Context, args); - return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None, - argTypes, FunctionType::ExtInfo(), {}, - RequiredArgs::All); + return arrangeLLVMFunctionInfo( + GetReturnType(resultType), /*instanceMethod=*/false, /*chainCall=*/false, + argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); } const CGFunctionInfo & CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType, ArrayRef<CanQualType> argTypes) { - return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::None, argTypes, - FunctionType::ExtInfo(), {}, - RequiredArgs::All); + return arrangeLLVMFunctionInfo( + resultType, /*instanceMethod=*/false, /*chainCall=*/false, + argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); } /// Arrange a call to a C++ method, passing the given arguments. @@ -698,15 +705,15 @@ CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args, auto argTypes = getArgTypesForCall(Context, args); FunctionType::ExtInfo info = proto->getExtInfo(); - return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()), - FnInfoOpts::IsInstanceMethod, argTypes, info, - paramInfos, required); + return arrangeLLVMFunctionInfo( + GetReturnType(proto->getReturnType()), /*instanceMethod=*/true, + /*chainCall=*/false, argTypes, info, paramInfos, required); } const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { - return arrangeLLVMFunctionInfo(getContext().VoidTy, FnInfoOpts::None, - std::nullopt, FunctionType::ExtInfo(), {}, - RequiredArgs::All); + return arrangeLLVMFunctionInfo( + getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, + std::nullopt, FunctionType::ExtInfo(), {}, RequiredArgs::All); } const CGFunctionInfo & @@ -726,15 +733,12 @@ CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, auto argTypes = getArgTypesForCall(Context, args); assert(signature.getRequiredArgs().allowsOptionalArgs()); - FnInfoOpts opts = FnInfoOpts::None; - if (signature.isInstanceMethod()) - opts |= FnInfoOpts::IsInstanceMethod; - if (signature.isChainCall()) - opts |= FnInfoOpts::IsChainCall; - if (signature.isDelegateCall()) - opts |= FnInfoOpts::IsDelegateCall; - return arrangeLLVMFunctionInfo(signature.getReturnType(), opts, argTypes, - signature.getExtInfo(), paramInfos, + return arrangeLLVMFunctionInfo(signature.getReturnType(), + signature.isInstanceMethod(), + signature.isChainCall(), + argTypes, + signature.getExtInfo(), + paramInfos, signature.getRequiredArgs()); } @@ -747,24 +751,21 @@ void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); /// Arrange the argument and result information for an abstract value /// of a given function type. This is the method which all of the /// above functions ultimately defer to. -const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo( - CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, - RequiredArgs required) { +const CGFunctionInfo & +CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, + bool instanceMethod, + bool chainCall, + ArrayRef<CanQualType> argTypes, + FunctionType::ExtInfo info, + ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, + RequiredArgs required) { assert(llvm::all_of(argTypes, [](CanQualType T) { return T.isCanonicalAsParam(); })); // Lookup or create unique function info. llvm::FoldingSetNodeID ID; - bool isInstanceMethod = - (opts & FnInfoOpts::IsInstanceMethod) == FnInfoOpts::IsInstanceMethod; - bool isChainCall = - (opts & FnInfoOpts::IsChainCall) == FnInfoOpts::IsChainCall; - bool isDelegateCall = - (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall; - CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall, - info, paramInfos, required, resultType, argTypes); + CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, paramInfos, + required, resultType, argTypes); void *insertPos = nullptr; CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos); @@ -774,8 +775,8 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo( unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); // Construct the function info. We co-allocate the ArgInfos. - FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall, - info, paramInfos, resultType, argTypes, required); + FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info, + paramInfos, resultType, argTypes, required); FunctionInfos.InsertNode(FI, insertPos); bool inserted = FunctionsBeingProcessed.insert(FI).second; @@ -810,8 +811,9 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo( return *FI; } -CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod, - bool chainCall, bool delegateCall, +CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, + bool instanceMethod, + bool chainCall, const FunctionType::ExtInfo &info, ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, @@ -831,7 +833,6 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod, FI->ASTCallingConvention = info.getCC(); FI->InstanceMethod = instanceMethod; FI->ChainCall = chainCall; - FI->DelegateCall = delegateCall; FI->CmseNSCall = info.getCmseNSCall(); FI->NoReturn = info.getNoReturn(); FI->ReturnsRetained = info.getProducesResult(); @@ -3984,6 +3985,10 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, QualType type = param->getType(); + if (isInAllocaArgument(CGM.getCXXABI(), type)) { + CGM.ErrorUnsupported(param, "forwarded non-trivially copyable parameter"); + } + // GetAddrOfLocalVar returns a pointer-to-pointer for references, // but the argument needs to be the original pointer. if (type->isReferenceType()) { diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 1cf2cd6cf28b1..824f0a9a88299 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -386,35 +386,6 @@ void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F, const TargetOptions &TargetOpts, bool WillInternalize); -enum class FnInfoOpts { - None = 0, - IsInstanceMethod = 1 << 0, - IsChainCall = 1 << 1, - IsDelegateCall = 1 << 2, -}; - -inline FnInfoOpts operator|(FnInfoOpts A, FnInfoOpts B) { - return static_cast<FnInfoOpts>( - static_cast<std::underlying_type_t<FnInfoOpts>>(A) | - static_cast<std::underlying_type_t<FnInfoOpts>>(B)); -} - -inline FnInfoOpts operator&(FnInfoOpts A, FnInfoOpts B) { - return static_cast<FnInfoOpts>( - static_cast<std::underlying_type_t<FnInfoOpts>>(A) & - static_cast<std::underlying_type_t<FnInfoOpts>>(B)); -} - -inline FnInfoOpts operator|=(FnInfoOpts A, FnInfoOpts B) { - A = A | B; - return A; -} - -inline FnInfoOpts operator&=(FnInfoOpts A, FnInfoOpts B) { - A = A & B; - return A; -} - } // end namespace CodeGen } // end namespace clang diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 40fb9bbbe8952..4bc8001d9605d 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2929,16 +2929,14 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad( } void CodeGenFunction::EmitForwardingCallToLambda( - const CXXMethodDecl *callOperator, CallArgList &callArgs, - const CGFunctionInfo *calleeFnInfo, llvm::Constant *calleePtr) { + const CXXMethodDecl *callOperator, + CallArgList &callArgs) { // Get the address of the call operator. - if (!calleeFnInfo) - calleeFnInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); - - if (!calleePtr) - calleePtr = - CGM.GetAddrOfFunction(GlobalDecl(callOperator), - CGM.getTypes().GetFunctionType(*calleeFnInfo)); + const CGFunctionInfo &calleeFnInfo = + CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); + llvm::Constant *calleePtr = + CGM.GetAddrOfFunction(GlobalDecl(callOperator), + CGM.getTypes().GetFunctionType(calleeFnInfo)); // Prepare the return slot. const FunctionProtoType *FPT = @@ -2946,8 +2944,8 @@ void CodeGenFunction::EmitForwardingCallToLambda( QualType resultType = FPT->getReturnType(); ReturnValueSlot returnSlot; if (!resultType->isVoidType() && - calleeFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && - !hasScalarEvaluationKind(calleeFnInfo->getReturnType())) + calleeFnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect && + !hasScalarEvaluationKind(calleeFnInfo.getReturnType())) returnSlot = ReturnValueSlot(ReturnValue, resultType.isVolatileQualified(), /*IsUnused=*/false, /*IsExternallyDestructed=*/true); @@ -2958,7 +2956,7 @@ void CodeGenFunction::EmitForwardingCallToLambda( // Now emit our call. auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator)); - RValue RV = EmitCall(*calleeFnInfo, callee, returnSlot, callArgs); + RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs); // If necessary, copy the returned value into the slot. if (!resultType->isVoidType() && returnSlot.isNull()) { @@ -3000,15 +2998,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { EmitForwardingCallToLambda(CallOp, CallArgs); } -void CodeGenFunction::EmitLambdaStaticInvokeBody(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; - } - +void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { const CXXRecordDecl *Lambda = MD->getParent(); // Start building arguments for forwarding call @@ -3019,16 +3009,10 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); - EmitLambdaDelegatingInvokeBody(MD, CallArgs); -} - -void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD, - CallArgList &CallArgs) { - // Add the rest of the forwarded parameters. + // Add the rest of the parameters. for (auto *Param : MD->parameters()) EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc()); - const CXXRecordDecl *Lambda = MD->getParent(); const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); // For a generic lambda, find the corresponding call operator specialization // to which the call to the static-invoker shall be forwarded. @@ -3042,21 +3026,10 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD, assert(CorrespondingCallOpSpecialization); CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization); } - - // Special lambda forwarding when there are inalloca parameters. - if (hasInAllocaArg(MD)) { - const CGFunctionInfo *ImplFnInfo = nullptr; - llvm::Function *ImplFn = nullptr; - EmitLambdaInAllocaImplFn(CallOp, &ImplFnInfo, &ImplFn); - - EmitForwardingCallToLambda(CallOp, CallArgs, ImplFnInfo, ImplFn); - return; - } - EmitForwardingCallToLambda(CallOp, CallArgs); } -void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) { +void CodeGenFunction::EmitLambdaStaticInvokeBody(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. @@ -3064,49 +3037,5 @@ void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) { return; } - // Forward %this argument. - CallArgList CallArgs; - QualType LambdaType = getContext().getRecordType(MD->getParent()); - QualType ThisType = getContext().getPointerType(LambdaType); - llvm::Value *ThisArg = CurFn->getArg(0); - CallArgs.add(RValue::get(ThisArg), ThisType); - - EmitLambdaDelegatingInvokeBody(MD, CallArgs); -} - -void CodeGenFunction::EmitLambdaInAllocaImplFn( - const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo, - llvm::Function **ImplFn) { - const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeCXXMethodDeclaration(CallOp); - llvm::Function *CallOpFn = - cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(CallOp))); - - // Emit function containing the original call op body. __invoke will delegate - // to this function. - SmallVector<CanQualType, 4> ArgTypes; - for (auto I = FnInfo.arg_begin(); I != FnInfo.arg_end(); ++I) - ArgTypes.push_back(I->type); - *ImplFnInfo = &CGM.getTypes().arrangeLLVMFunctionInfo( - FnInfo.getReturnType(), FnInfoOpts::IsDelegateCall, ArgTypes, - FnInfo.getExtInfo(), {}, FnInfo.getRequiredArgs()); - - // Create mangled name as if this was a method named __impl. - StringRef CallOpName = CallOpFn->getName(); - std::string ImplName = - ("?__impl@" + CallOpName.drop_front(CallOpName.find_first_of("<"))).str(); - - llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName); - if (!Fn) { - Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(**ImplFnInfo), - llvm::GlobalValue::InternalLinkage, ImplName, - CGM.getModule()); - CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo); - - const GlobalDecl &GD = GlobalDecl(CallOp); - const auto *D = cast<FunctionDecl>(GD.getDecl()); - CodeGenFunction(CGM).GenerateCode(GD, Fn, **ImplFnInfo); - CGM.SetLLVMFunctionAttributesForDefinition(D, Fn); - } - *ImplFn = Fn; + EmitLambdaDelegatingInvokeBody(MD); } diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 772d5cf30b1c6..8a77ffeed52f7 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -279,8 +279,8 @@ llvm::Function *CodeGenFunction::createTLSAtExitStub( } const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo( - getContext().IntTy, FnInfoOpts::None, {getContext().IntTy}, - FunctionType::ExtInfo(), {}, RequiredArgs::All); + getContext().IntTy, /*instanceMethod=*/false, /*chainCall=*/false, + {getContext().IntTy}, FunctionType::ExtInfo(), {}, RequiredArgs::All); // Get the stub function type, int(*)(int,...). llvm::FunctionType *StubTy = diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp index a6073e1188d6f..d3a16a1d5accf 100644 --- a/clang/lib/CodeGen/CodeGenABITypes.cpp +++ b/clang/lib/CodeGen/CodeGenABITypes.cpp @@ -65,8 +65,9 @@ CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM, ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info, RequiredArgs args) { - return CGM.getTypes().arrangeLLVMFunctionInfo(returnType, FnInfoOpts::None, - argTypes, info, {}, args); + return CGM.getTypes().arrangeLLVMFunctionInfo( + returnType, /*instanceMethod=*/false, /*chainCall=*/false, argTypes, + info, {}, args); } ImplicitCXXConstructorArgs diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 6899388a842db..b8d39371a9330 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -683,19 +683,6 @@ static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) { return true; } -bool CodeGenFunction::isInAllocaArgument(CGCXXABI &ABI, QualType Ty) { - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; -} - -bool CodeGenFunction::hasInAllocaArg(const CXXMethodDecl *MD) { - return getTarget().getTriple().getArch() == llvm::Triple::x86 && - getTarget().getCXXABI().isMicrosoft() && - llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) { - return isInAllocaArgument(CGM.getCXXABI(), P->getType()); - }); -} - /// Return the UBSan prologue signature for \p FD if one is available. static llvm::Constant *getPrologueSignature(CodeGenModule &CGM, const FunctionDecl *FD) { @@ -1460,17 +1447,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // The lambda static invoker function is special, because it forwards or // clones the body of the function call operator (but is actually static). EmitLambdaStaticInvokeBody(cast<CXXMethodDecl>(FD)); - - } else if (isa<CXXMethodDecl>(FD) && - isLambdaCallOperator(cast<CXXMethodDecl>(FD)) && - cast<CXXMethodDecl>(FD)->getParent()->getLambdaStaticInvoker() && - hasInAllocaArg(cast<CXXMethodDecl>(FD) - ->getParent() - ->getLambdaStaticInvoker()) && - !FnInfo.isDelegateCall()) { - // If emitting a lambda with static invoker on X86 Windows, change - // the call operator body. - EmitLambdaInAllocaCallOpBody(cast<CXXMethodDecl>(FD)); } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) && (cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator() || cast<CXXMethodDecl>(FD)->isMoveAssignmentOperator())) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 09a8c0779c460..0f720596165ff 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1963,9 +1963,6 @@ class CodeGenFunction : public CodeGenTypeCache { /// Check if the return value of this function requires sanitization. bool requiresReturnValueCheck() const; - bool isInAllocaArgument(CGCXXABI &ABI, QualType Ty); - bool hasInAllocaArg(const CXXMethodDecl *MD); - llvm::BasicBlock *TerminateLandingPad = nullptr; llvm::BasicBlock *TerminateHandler = nullptr; llvm::SmallVector<llvm::BasicBlock *, 2> TrapBBs; @@ -2228,17 +2225,10 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S); void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator, - CallArgList &CallArgs, - const CGFunctionInfo *CallOpFnInfo = nullptr, - llvm::Constant *CallOpFn = nullptr); + CallArgList &CallArgs); void EmitLambdaBlockInvokeBody(); + void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD); void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD); - void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD, - CallArgList &CallArgs); - void EmitLambdaInAllocaImplFn(const CXXMethodDecl *CallOp, - const CGFunctionInfo **ImplFnInfo, - llvm::Function **ImplFn); - void EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD); void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) { EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); } diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index a0e846d9a7516..9088f77b95c34 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -252,11 +252,13 @@ class CodeGenTypes { /// this. /// /// \param argTypes - must all actually be canonical as params - const CGFunctionInfo &arrangeLLVMFunctionInfo( - CanQualType returnType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, - RequiredArgs args); + const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType, + bool instanceMethod, + bool chainCall, + ArrayRef<CanQualType> argTypes, + FunctionType::ExtInfo info, + ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, + RequiredArgs args); /// Compute a new LLVM record layout object for the given record. std::unique_ptr<CGRecordLayout> ComputeRecordLayout(const RecordDecl *D, diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index f48410d565151..d08e7cef5bce4 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -140,8 +140,7 @@ class X86_32ABIInfo : public ABIInfo { Class classify(QualType Ty) const; ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const; - ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State, - bool isDelegateCall) const; + ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; /// Updates the number of available free registers, returns /// true if any registers were allocated. @@ -739,8 +738,8 @@ void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State) c } } -ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, - bool isDelegateCall) const { +ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, + CCState &State) const { // FIXME: Set alignment on indirect arguments. bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall; bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall; @@ -753,7 +752,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, const RecordType *RT = Ty->getAs<RecordType>(); if (RT) { CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); - if (RAA == CGCXXABI::RAA_Indirect || isDelegateCall) { + if (RAA == CGCXXABI::RAA_Indirect) { return getIndirectResult(Ty, false, State); } else if (RAA == CGCXXABI::RAA_DirectInMemory) { // The field index doesn't matter, we'll fix it up later. @@ -942,8 +941,7 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const { if (State.IsPreassigned.test(I)) continue; - Args[I].info = - classifyArgumentType(Args[I].type, State, FI.isDelegateCall()); + Args[I].info = classifyArgumentType(Args[I].type, State); UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca); } diff --git a/clang/test/CodeGenCXX/inalloca-lambda.cpp b/clang/test/CodeGenCXX/inalloca-lambda.cpp index 19b20fe055f02..ac85ee175268b 100644 --- a/clang/test/CodeGenCXX/inalloca-lambda.cpp +++ b/clang/test/CodeGenCXX/inalloca-lambda.cpp @@ -1,50 +1,11 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s 2>&1 | FileCheck %s -struct A { - A(); +// PR28299 +// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet + +class A { A(const A &); - int x; }; -void decayToFp(int (*f)(A)); -void test() { - auto ld = [](A a) { - static int calls = 0; - ++calls; - return a.x + calls; - }; - decayToFp(ld); - ld(A{}); -} - -// CHECK: define internal x86_thiscallcc noundef i32 -// CHECK-SAME: @"??R<lambda_0>@?0??test@@YAXXZ@QBE?A?<auto>@@UA@@@Z" -// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %struct.A }>) %[[ARG:.*]]) -// CHECK: %[[V:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0 -// CHECK: %call = call x86_thiscallcc noundef i32 -// CHECK-SAME: @"?__impl@<lambda_0>@?0??test@@YAXXZ@QBE?A?<auto>@@UA@@@Z" -// CHECK-SAME: (ptr noundef %this, ptr noundef %[[V]]) - -// CHECK: define internal noundef i32 -// CHECK-SAME: @"?__invoke@<lambda_0>@?0??test@@YAXXZ@CA?A?<auto>@@UA@@@Z" -// CHECK-SAME: (ptr inalloca(<{ %struct.A }>) %[[ARG:.*]]) -// CHECK: %unused.capture = alloca %class.anon, align 1 -// CHECK: %[[VAR:.*]] = getelementptr inbounds <{ %struct.A }>, ptr %[[ARG]], i32 0, i32 0 -// CHECK: %call = call x86_thiscallcc noundef i32 -// CHECK-SAME: @"?__impl@<lambda_0>@?0??test@@YAXXZ@QBE?A?<auto>@@UA@@@Z" -// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %[[VAR]]) -// CHECK: ret i32 %call +typedef void (*fptr_t)(A); +fptr_t fn1() { return [](A) {}; } -// CHECK: define internal x86_thiscallcc noundef i32 -// CHECK-SAME: @"?__impl@<lambda_0>@?0??test@@YAXXZ@QBE?A?<auto>@@UA@@@Z" -// CHECK-SAME: (ptr noundef %this, ptr noundef %[[ARG:.*]]) -// CHECK: %this.addr = alloca ptr, align 4 -// CHECK: store ptr %this, ptr %this.addr, align 4 -// CHECK: %this1 = load ptr, ptr %this.addr, align 4 -// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R<lambda_0> -// CHECK: %inc = add nsw i32 %{{.*}}, 1 -// CHECK: store i32 %inc, ptr @"?calls@?1???R<lambda_0> -// CHECK: %{{.*}} = getelementptr inbounds %struct.A, ptr %{{.*}}, i32 0, i32 0 -// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 4 -// CHECK: %{{.*}} = load i32, ptr @"?calls@?1???R<lambda_0> -// CHECK: %add = add nsw i32 %{{.*}}, %{{.*}} -// CHECK: ret i32 %add _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits