akhuang updated this revision to Diff 476634. akhuang added a comment. cleanup
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D137872/new/ https://reviews.llvm.org/D137872 Files: 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.h clang/lib/CodeGen/CodeGenTypes.h clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGenCXX/inalloca-lambda.cpp
Index: clang/test/CodeGenCXX/inalloca-lambda.cpp =================================================================== --- clang/test/CodeGenCXX/inalloca-lambda.cpp +++ clang/test/CodeGenCXX/inalloca-lambda.cpp @@ -1,7 +1,4 @@ -// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s 2>&1 | FileCheck %s - -// PR28299 -// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s 2>&1 | FileCheck %s class A { A(const A &); @@ -9,3 +6,23 @@ typedef void (*fptr_t)(A); fptr_t fn1() { return [](A) {}; } + +// CHECK: define internal void @"?__invoke@<lambda_0>@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?<auto>@@0@Z" +// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0) +// CHECK: %unused.capture = alloca %class.anon, align 1 +// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0 +// CHECK: call x86_thiscallcc void @"??R<lambda_0>@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?<auto>@@0...@z.impl" +// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %1) +// CHECK: ret void + +// CHECK: define internal x86_thiscallcc void @"??R<lambda_0>@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?<auto>@@0@Z" +// CHECK-SAME: (ptr noundef %this, ptr inalloca(<{ %class.A, [3 x i8] }>) %0) +// CHECK: call x86_thiscallcc void @"??R<lambda_0>@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?<auto>@@0...@z.impl" +// CHECK-SAME: (ptr noundef %unused.capture, ptr noundef %1) + +// CHECK: define internal x86_thiscallcc void @"??R<lambda_0>@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?<auto>@@0...@z.impl" +// CHECK-SAME: (ptr noundef %this, ptr noundef %0) +// 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: ret void Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -1187,7 +1187,7 @@ Class classify(QualType Ty) const; ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const; - ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; + ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State, bool NoInAlloca) const; /// Updates the number of available free registers, returns /// true if any registers were allocated. @@ -1824,7 +1824,8 @@ } ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, - CCState &State) const { + CCState &State, + bool NoInAlloca) const { // FIXME: Set alignment on indirect arguments. bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall; bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall; @@ -1840,6 +1841,8 @@ if (RAA == CGCXXABI::RAA_Indirect) { return getIndirectResult(Ty, false, State); } else if (RAA == CGCXXABI::RAA_DirectInMemory) { + if (NoInAlloca) + return getIndirectResult(Ty, false, State); // The field index doesn't matter, we'll fix it up later. return ABIArgInfo::getInAlloca(/*FieldIndex=*/0); } @@ -2014,7 +2017,7 @@ if (State.IsPreassigned.test(I)) continue; - Args[I].info = classifyArgumentType(Args[I].type, State); + Args[I].info = classifyArgumentType(Args[I].type, State, FI.isAvoidingInAlloca()); UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca); } Index: clang/lib/CodeGen/CodeGenTypes.h =================================================================== --- clang/lib/CodeGen/CodeGenTypes.h +++ clang/lib/CodeGen/CodeGenTypes.h @@ -260,8 +260,7 @@ /// /// \param argTypes - must all actually be canonical as params const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType, - bool instanceMethod, - bool chainCall, + FnInfoOptions opts, ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info, ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, Index: clang/lib/CodeGen/CodeGenFunction.h =================================================================== --- clang/lib/CodeGen/CodeGenFunction.h +++ clang/lib/CodeGen/CodeGenFunction.h @@ -2219,10 +2219,16 @@ void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S); void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator, - CallArgList &CallArgs); + CallArgList &CallArgs, + const CGFunctionInfo *CallOpFnInfo = nullptr, + llvm::Constant *CallOpFn = nullptr); void EmitLambdaBlockInvokeBody(); void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD); void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD); + void EmitLambdaInAllocaCallOpFn(const CXXMethodDecl *MD); + void EmitLambdaInAllocaImplFn(const CXXMethodDecl *CallOp, + const CGFunctionInfo **ImplFnInfo, + llvm::Function **ImplFn); void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) { EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); } Index: clang/lib/CodeGen/CodeGenABITypes.cpp =================================================================== --- clang/lib/CodeGen/CodeGenABITypes.cpp +++ clang/lib/CodeGen/CodeGenABITypes.cpp @@ -65,9 +65,8 @@ ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info, RequiredArgs args) { - return CGM.getTypes().arrangeLLVMFunctionInfo( - returnType, /*instanceMethod=*/false, /*chainCall=*/false, argTypes, - info, {}, args); + return CGM.getTypes().arrangeLLVMFunctionInfo(returnType, FnInfoOptions(), + argTypes, info, {}, args); } ImplicitCXXConstructorArgs Index: clang/lib/CodeGen/CGDeclCXX.cpp =================================================================== --- clang/lib/CodeGen/CGDeclCXX.cpp +++ clang/lib/CodeGen/CGDeclCXX.cpp @@ -278,7 +278,7 @@ } const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo( - getContext().IntTy, /*instanceMethod=*/false, /*chainCall=*/false, + getContext().IntTy, FnInfoOptions(), {getContext().IntTy}, FunctionType::ExtInfo(), {}, RequiredArgs::All); // Get the stub function type, int(*)(int,...). Index: clang/lib/CodeGen/CGClass.cpp =================================================================== --- clang/lib/CodeGen/CGClass.cpp +++ clang/lib/CodeGen/CGClass.cpp @@ -2935,13 +2935,16 @@ void CodeGenFunction::EmitForwardingCallToLambda( const CXXMethodDecl *callOperator, - CallArgList &callArgs) { + CallArgList &callArgs, + const CGFunctionInfo *calleeFnInfo, + llvm::Constant *calleePtr) { // Get the address of the call operator. - const CGFunctionInfo &calleeFnInfo = - CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); - llvm::Constant *calleePtr = - CGM.GetAddrOfFunction(GlobalDecl(callOperator), - CGM.getTypes().GetFunctionType(calleeFnInfo)); + if (!calleeFnInfo) + calleeFnInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); + + if (!calleePtr) + calleePtr = CGM.GetAddrOfFunction(GlobalDecl(callOperator), + CGM.getTypes().GetFunctionType(*calleeFnInfo)); // Prepare the return slot. const FunctionProtoType *FPT = @@ -2949,8 +2952,8 @@ 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); @@ -2961,7 +2964,7 @@ // 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()) { @@ -3003,6 +3006,18 @@ EmitForwardingCallToLambda(CallOp, CallArgs); } +static bool isInAllocaArg(CGCXXABI &ABI, QualType T) { + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; +} + +static bool hasInAllocaArg(const TargetInfo &TI, CGCXXABI &ABI, const CXXMethodDecl *MD) { + return TI.getCXXABI().isMicrosoft() && + llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) { + return isInAllocaArg(ABI, P->getType()); + }); +} + void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { const CXXRecordDecl *Lambda = MD->getParent(); @@ -3031,6 +3046,17 @@ assert(CorrespondingCallOpSpecialization); CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization); } + + // Special lambda forwarding when there are inalloca parameters. + if (hasInAllocaArg(getTarget(), CGM.getCXXABI(), MD)) { + const CGFunctionInfo *ImplFnInfo = nullptr; + llvm::Function *ImplFn = nullptr; + EmitLambdaInAllocaImplFn(CallOp, &ImplFnInfo, &ImplFn); + + EmitForwardingCallToLambda(CallOp, CallArgs, ImplFnInfo, ImplFn); + return; + } + EmitForwardingCallToLambda(CallOp, CallArgs); } @@ -3042,5 +3068,80 @@ return; } + // If there are inalloca params, generate a new function containing the lambda body + // and make the invoker and original call operator call that function. + // Emit the new call operator here. + if (hasInAllocaArg(getTarget(), CGM.getCXXABI(), MD)) + EmitLambdaInAllocaCallOpFn(MD); + EmitLambdaDelegatingInvokeBody(MD); } + +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 impl function containing the original lambda body. + SmallVector<CanQualType, 4> ArgTypes; + for (auto I = FnInfo.arg_begin(); I != FnInfo.arg_end(); ++I) + ArgTypes.push_back(I->type); + FnInfoOptions Opts(/*IsInstanceMethod*/false, /*IsChainCall*/false, /*DontInAlloca*/true); + *ImplFnInfo = &CGM.getTypes().arrangeLLVMFunctionInfo( + FnInfo.getReturnType(), Opts, ArgTypes, + FnInfo.getExtInfo(), {}, FnInfo.getRequiredArgs()); + + std::string ImplName = (CallOpFn->getName() + ".impl").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); + CodeGenFunction CGF(CGM); + CGF.CurGD = GlobalDecl(CallOp); + const FunctionDecl *FD = cast<FunctionDecl>(CurGD.getDecl()); + + FunctionArgList Args; + QualType ResTy = CGF.BuildFunctionArgList(CurGD, Args); + + CGF.StartFunction(CurGD, ResTy, Fn, **ImplFnInfo, Args, + FD->getLocation(), FD->getLocation()); + CGF.EmitFunctionBody(FD->getBody()); + CGF.FinishFunction(); + } + *ImplFn = Fn; +} + +void CodeGenFunction::EmitLambdaInAllocaCallOpFn(const CXXMethodDecl *MD) { + const CXXMethodDecl *CallOp = MD->getParent()->getLambdaCallOperator(); + const CGFunctionInfo &FnInfo = + CGM.getTypes().arrangeCXXMethodDeclaration(CallOp); + llvm::Function *CallOpFn = + cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(CallOp))); + + // Emit new call operator. + llvm::Function *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(FnInfo), + llvm::GlobalValue::InternalLinkage, + "tmp", CGM.getModule()); + CGM.SetInternalFunctionAttributes(CallOp, Fn, FnInfo); + + CodeGenFunction CGF(CGM); + CGF.CurGD = GlobalDecl(CallOp); + const FunctionDecl *FD = cast<FunctionDecl>(CGF.CurGD.getDecl()); + + FunctionArgList Args; + QualType ResTy = CGF.BuildFunctionArgList(CGF.CurGD, Args); + + CGF.StartFunction(CGF.CurGD, ResTy, Fn, FnInfo, Args, + FD->getLocation(), FD->getLocation()); + CGF.EmitLambdaDelegatingInvokeBody(CallOp); + CGF.FinishFunction(); + + CallOpFn->replaceAllUsesWith(Fn); + Fn->takeName(CallOpFn); + CallOpFn->eraseFromParent(); +} Index: clang/lib/CodeGen/CGCall.h =================================================================== --- clang/lib/CodeGen/CGCall.h +++ clang/lib/CodeGen/CGCall.h @@ -377,6 +377,22 @@ bool isExternallyDestructed() const { return IsExternallyDestructed; } }; +class FnInfoOptions { + unsigned IsInstanceMethod : 1; + unsigned IsChainCall : 1; + unsigned DontInAlloca : 1; + +public: + FnInfoOptions() + : IsInstanceMethod(false), IsChainCall(false), DontInAlloca(false) {} + FnInfoOptions(bool IsInstanceMethod, bool IsChainCall, bool DontInAlloca) + : IsInstanceMethod(IsInstanceMethod), IsChainCall(IsChainCall), DontInAlloca(DontInAlloca) {} + + bool isInstanceMethod() const { return IsInstanceMethod; } + bool isChainCall() const { return IsChainCall; } + bool isAvoidInAlloca() const { return DontInAlloca; } +}; + } // end namespace CodeGen } // end namespace clang Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -111,9 +111,8 @@ // When translating an unprototyped function type, always use a // variadic type. return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(), - /*instanceMethod=*/false, - /*chainCall=*/false, None, - FTNP->getExtInfo(), {}, RequiredArgs(0)); + FnInfoOptions(), None, FTNP->getExtInfo(), {}, + RequiredArgs(0)); } static void addExtParameterInfosForCall( @@ -188,10 +187,9 @@ appendParameterTypes(CGT, prefix, paramInfos, FTP); CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); - return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, - /*chainCall=*/false, prefix, - FTP->getExtInfo(), paramInfos, - Required); + FnInfoOptions opts(instanceMethod, /*IsChainCall*/false, /*DontInAlloca*/false); + return CGT.arrangeLLVMFunctionInfo(resultType, opts, prefix, FTP->getExtInfo(), + paramInfos, Required); } /// Arrange the argument and result information for a value of the @@ -270,7 +268,7 @@ argTypes.push_back(DeriveThisType(RD, MD)); return ::arrangeLLVMFunctionInfo( - *this, true, argTypes, + *this, /*instanceMethod=*/true, argTypes, FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>()); } @@ -360,9 +358,8 @@ : TheCXXABI.hasMostDerivedReturn(GD) ? CGM.getContext().VoidPtrTy : Context.VoidTy; - return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, extInfo, - paramInfos, required); + FnInfoOptions opts(/*IsInstanceMethod*/true, /*IsChainCall*/false, /*DontInAlloca*/false); + return arrangeLLVMFunctionInfo(resultType, opts, argTypes, extInfo, paramInfos, required); } static SmallVector<CanQualType, 16> @@ -436,9 +433,9 @@ addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs, ArgTypes.size()); } - return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true, - /*chainCall=*/false, ArgTypes, Info, - ParamInfos, Required); + + FnInfoOptions Opts(/*IsInstanceMethod=*/true, /*IsChainCall*/false, /*DontInAlloca*/false); + return arrangeLLVMFunctionInfo(ResultType, Opts, ArgTypes, Info, ParamInfos, Required); } /// Arrange the argument and result information for the declaration or @@ -458,8 +455,8 @@ // non-variadic type. if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) { return arrangeLLVMFunctionInfo( - noProto->getReturnType(), /*instanceMethod=*/false, - /*chainCall=*/false, None, noProto->getExtInfo(), {},RequiredArgs::All); + noProto->getReturnType(), FnInfoOptions(), + None, noProto->getExtInfo(), {},RequiredArgs::All); } return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>()); @@ -509,8 +506,7 @@ (MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All); return arrangeLLVMFunctionInfo( - GetReturnType(MD->getReturnType()), /*instanceMethod=*/false, - /*chainCall=*/false, argTys, einfo, extParamInfos, required); + GetReturnType(MD->getReturnType()), FnInfoOptions(), argTys, einfo, extParamInfos, required); } const CGFunctionInfo & @@ -520,8 +516,8 @@ FunctionType::ExtInfo einfo; return arrangeLLVMFunctionInfo( - GetReturnType(returnType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, einfo, {}, RequiredArgs::All); + GetReturnType(returnType), FnInfoOptions(), argTypes, einfo, {}, + RequiredArgs::All); } const CGFunctionInfo & @@ -546,8 +542,7 @@ assert(MD->isVirtual() && "only methods have thunks"); CanQual<FunctionProtoType> FTP = GetFormalType(MD); CanQualType ArgTys[] = {DeriveThisType(MD->getParent(), MD)}; - return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false, - /*chainCall=*/false, ArgTys, + return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOptions(), ArgTys, FTP->getExtInfo(), {}, RequiredArgs(1)); } @@ -566,10 +561,9 @@ ArgTys.push_back(Context.IntTy); CallingConv CC = Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true); - return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true, - /*chainCall=*/false, ArgTys, - FunctionType::ExtInfo(CC), {}, - RequiredArgs::All); + FnInfoOptions Opts(/*IsInstanceMethod=*/true, /*IsChainCall*/false, /*DontInAlloca*/false); + return arrangeLLVMFunctionInfo(Context.VoidTy, Opts, ArgTys, FunctionType::ExtInfo(CC), + {}, RequiredArgs::All); } /// Arrange a call as unto a free function, except possibly with an @@ -612,8 +606,8 @@ SmallVector<CanQualType, 16> argTypes; for (const auto &arg : args) argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty)); - return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), - /*instanceMethod=*/false, chainCall, + FnInfoOptions opts(/*IsInstanceMethod=*/false, chainCall, /*DontInAlloca=*/false); + return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), opts, argTypes, fnType->getExtInfo(), paramInfos, required); } @@ -645,8 +639,7 @@ auto paramInfos = getExtParameterInfosForCall(proto, 1, params.size()); auto argTypes = getArgTypesForDeclaration(Context, params); - return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()), - /*instanceMethod*/ false, /*chainCall*/ false, + return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()), FnInfoOptions(), argTypes, proto->getExtInfo(), paramInfos, RequiredArgs::forPrototypePlus(proto, 1)); } @@ -659,8 +652,8 @@ for (const auto &Arg : args) argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, FunctionType::ExtInfo(), + GetReturnType(resultType), FnInfoOptions(), + argTypes, FunctionType::ExtInfo(), /*paramInfos=*/ {}, RequiredArgs::All); } @@ -670,16 +663,16 @@ auto argTypes = getArgTypesForDeclaration(Context, args); return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); + GetReturnType(resultType), FnInfoOptions(), argTypes, FunctionType::ExtInfo(), + {}, RequiredArgs::All); } const CGFunctionInfo & CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType, ArrayRef<CanQualType> argTypes) { return arrangeLLVMFunctionInfo( - resultType, /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); + resultType, FnInfoOptions(), argTypes, FunctionType::ExtInfo(), {}, + RequiredArgs::All); } /// Arrange a call to a C++ method, passing the given arguments. @@ -702,15 +695,15 @@ auto argTypes = getArgTypesForCall(Context, args); FunctionType::ExtInfo info = proto->getExtInfo(); + FnInfoOptions opts( + /*IsInstanceMethod=*/true, /*IsChainCall=*/false, /*DontInAlloca=*/false); return arrangeLLVMFunctionInfo( - GetReturnType(proto->getReturnType()), /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, info, paramInfos, required); + GetReturnType(proto->getReturnType()), opts, argTypes, info, paramInfos, required); } const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { return arrangeLLVMFunctionInfo( - getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, - None, FunctionType::ExtInfo(), {}, RequiredArgs::All); + getContext().VoidTy, FnInfoOptions(), None, FunctionType::ExtInfo(), {}, RequiredArgs::All); } const CGFunctionInfo & @@ -730,9 +723,10 @@ auto argTypes = getArgTypesForCall(Context, args); assert(signature.getRequiredArgs().allowsOptionalArgs()); + FnInfoOptions opts(signature.isInstanceMethod(), signature.isChainCall(), + signature.isAvoidingInAlloca()); return arrangeLLVMFunctionInfo(signature.getReturnType(), - signature.isInstanceMethod(), - signature.isChainCall(), + opts, argTypes, signature.getExtInfo(), paramInfos, @@ -750,8 +744,7 @@ /// above functions ultimately defer to. const CGFunctionInfo & CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, - bool instanceMethod, - bool chainCall, + FnInfoOptions opts, ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info, ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, @@ -761,7 +754,7 @@ // Lookup or create unique function info. llvm::FoldingSetNodeID ID; - CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, paramInfos, + CGFunctionInfo::Profile(ID, opts.isInstanceMethod(), opts.isChainCall(), info, paramInfos, required, resultType, argTypes); void *insertPos = nullptr; @@ -772,8 +765,9 @@ unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); // Construct the function info. We co-allocate the ArgInfos. - FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info, - paramInfos, resultType, argTypes, required); + FI = CGFunctionInfo::create(CC, opts.isInstanceMethod(), opts.isChainCall(), + opts.isAvoidInAlloca(), info, paramInfos, resultType, + argTypes, required); FunctionInfos.InsertNode(FI, insertPos); bool inserted = FunctionsBeingProcessed.insert(FI).second; @@ -811,6 +805,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod, bool chainCall, + bool dontInAlloca, const FunctionType::ExtInfo &info, ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, @@ -830,6 +825,7 @@ FI->ASTCallingConvention = info.getCC(); FI->InstanceMethod = instanceMethod; FI->ChainCall = chainCall; + FI->DontInAlloca = dontInAlloca, FI->CmseNSCall = info.getCmseNSCall(); FI->NoReturn = info.getNoReturn(); FI->ReturnsRetained = info.getProducesResult(); @@ -3806,10 +3802,6 @@ 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()) { Index: clang/include/clang/CodeGen/CGFunctionInfo.h =================================================================== --- clang/include/clang/CodeGen/CGFunctionInfo.h +++ clang/include/clang/CodeGen/CGFunctionInfo.h @@ -567,6 +567,9 @@ /// Whether this is a chain call. unsigned ChainCall : 1; + /// Whether this function should avoid inalloca arguments. + unsigned DontInAlloca: 1; + /// Whether this function is a CMSE nonsecure call unsigned CmseNSCall : 1; @@ -619,6 +622,7 @@ static CGFunctionInfo *create(unsigned llvmCC, bool instanceMethod, bool chainCall, + bool dontInAlloca, const FunctionType::ExtInfo &extInfo, ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, @@ -663,6 +667,8 @@ bool isChainCall() const { return ChainCall; } + bool isAvoidingInAlloca() const { return DontInAlloca; } + bool isCmseNSCall() const { return CmseNSCall; } bool isNoReturn() const { return NoReturn; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits