@@ -198,7 +198,8 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) {
198
198
FTP);
199
199
}
200
200
201
- static CallingConv getCallingConventionForDecl (const Decl *D, bool IsWindows) {
201
+ static CallingConv getCallingConventionForDecl (const ObjCMethodDecl *D,
202
+ bool IsWindows) {
202
203
// Set the appropriate calling convention for the Function.
203
204
if (D->hasAttr <StdCallAttr>())
204
205
return CC_X86StdCall;
@@ -3761,13 +3762,107 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
3761
3762
EmitCheck (std::make_pair (Cond, CheckKind), Handler, StaticData, None);
3762
3763
}
3763
3764
3765
+ // Check if the call is going to use the inalloca convention. This needs to
3766
+ // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged
3767
+ // later, so we can't check it directly.
3768
+ static bool hasInAllocaArgs (CodeGenModule &CGM, CallingConv ExplicitCC,
3769
+ ArrayRef<QualType> ArgTypes) {
3770
+ // The Swift calling convention doesn't go through the target-specific
3771
+ // argument classification, so it never uses inalloca.
3772
+ // TODO: Consider limiting inalloca use to only calling conventions supported
3773
+ // by MSVC.
3774
+ if (ExplicitCC == CC_Swift)
3775
+ return false ;
3776
+ if (!CGM.getTarget ().getCXXABI ().isMicrosoft ())
3777
+ return false ;
3778
+ return llvm::any_of (ArgTypes, [&](QualType Ty) {
3779
+ return isInAllocaArgument (CGM.getCXXABI (), Ty);
3780
+ });
3781
+ }
3782
+
3783
+ #ifndef NDEBUG
3784
+ // Determine whether the given argument is an Objective-C method
3785
+ // that may have type parameters in its signature.
3786
+ static bool isObjCMethodWithTypeParams (const ObjCMethodDecl *method) {
3787
+ const DeclContext *dc = method->getDeclContext ();
3788
+ if (const ObjCInterfaceDecl *classDecl = dyn_cast<ObjCInterfaceDecl>(dc)) {
3789
+ return classDecl->getTypeParamListAsWritten ();
3790
+ }
3791
+
3792
+ if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) {
3793
+ return catDecl->getTypeParamList ();
3794
+ }
3795
+
3796
+ return false ;
3797
+ }
3798
+ #endif
3799
+
3800
+ // / EmitCallArgs - Emit call arguments for a function.
3764
3801
void CodeGenFunction::EmitCallArgs (
3765
- CallArgList &Args, ArrayRef<QualType> ArgTypes ,
3802
+ CallArgList &Args, PrototypeWrapper Prototype ,
3766
3803
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
3767
3804
AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) {
3805
+ SmallVector<QualType, 16 > ArgTypes;
3806
+
3807
+ assert ((ParamsToSkip == 0 || Prototype.P ) &&
3808
+ " Can't skip parameters if type info is not provided" );
3809
+
3810
+ // This variable only captures *explicitly* written conventions, not those
3811
+ // applied by default via command line flags or target defaults, such as
3812
+ // thiscall, aapcs, stdcall via -mrtd, etc. Computing that correctly would
3813
+ // require knowing if this is a C++ instance method or being able to see
3814
+ // unprototyped FunctionTypes.
3815
+ CallingConv ExplicitCC = CC_C;
3816
+
3817
+ // First, if a prototype was provided, use those argument types.
3818
+ bool IsVariadic = false ;
3819
+ if (Prototype.P ) {
3820
+ const auto *MD = Prototype.P .dyn_cast <const ObjCMethodDecl *>();
3821
+ if (MD) {
3822
+ IsVariadic = MD->isVariadic ();
3823
+ ExplicitCC = getCallingConventionForDecl (
3824
+ MD, CGM.getTarget ().getTriple ().isOSWindows ());
3825
+ ArgTypes.assign (MD->param_type_begin () + ParamsToSkip,
3826
+ MD->param_type_end ());
3827
+ } else {
3828
+ const auto *FPT = Prototype.P .get <const FunctionProtoType *>();
3829
+ IsVariadic = FPT->isVariadic ();
3830
+ ExplicitCC = FPT->getExtInfo ().getCC ();
3831
+ ArgTypes.assign (FPT->param_type_begin () + ParamsToSkip,
3832
+ FPT->param_type_end ());
3833
+ }
3834
+
3835
+ #ifndef NDEBUG
3836
+ // Check that the prototyped types match the argument expression types.
3837
+ bool isGenericMethod = MD && isObjCMethodWithTypeParams (MD);
3838
+ CallExpr::const_arg_iterator Arg = ArgRange.begin ();
3839
+ for (QualType Ty : ArgTypes) {
3840
+ assert (Arg != ArgRange.end () && " Running over edge of argument list!" );
3841
+ assert (
3842
+ (isGenericMethod || Ty->isVariablyModifiedType () ||
3843
+ Ty.getNonReferenceType ()->isObjCRetainableType () ||
3844
+ getContext ()
3845
+ .getCanonicalType (Ty.getNonReferenceType ())
3846
+ .getTypePtr () ==
3847
+ getContext ().getCanonicalType ((*Arg)->getType ()).getTypePtr ()) &&
3848
+ " type mismatch in call argument!" );
3849
+ ++Arg;
3850
+ }
3851
+
3852
+ // Either we've emitted all the call args, or we have a call to variadic
3853
+ // function.
3854
+ assert ((Arg == ArgRange.end () || IsVariadic) &&
3855
+ " Extra arguments in non-variadic function!" );
3856
+ #endif
3857
+ }
3858
+
3859
+ // If we still have any arguments, emit them using the type of the argument.
3860
+ for (auto *A : llvm::make_range (std::next (ArgRange.begin (), ArgTypes.size ()),
3861
+ ArgRange.end ()))
3862
+ ArgTypes.push_back (IsVariadic ? getVarArgType (A) : A->getType ());
3768
3863
assert ((int )ArgTypes.size () == (ArgRange.end () - ArgRange.begin ()));
3769
3864
3770
- // We *have* to evaluate arguments from right to left in the MS C++ ABI,
3865
+ // We must evaluate arguments from right to left in the MS C++ ABI,
3771
3866
// because arguments are destroyed left to right in the callee. As a special
3772
3867
// case, there are certain language constructs that require left-to-right
3773
3868
// evaluation, and in those cases we consider the evaluation order requirement
@@ -3800,15 +3895,10 @@ void CodeGenFunction::EmitCallArgs(
3800
3895
};
3801
3896
3802
3897
// Insert a stack save if we're going to need any inalloca args.
3803
- bool HasInAllocaArgs = false ;
3804
- if (CGM.getTarget ().getCXXABI ().isMicrosoft ()) {
3805
- for (ArrayRef<QualType>::iterator I = ArgTypes.begin (), E = ArgTypes.end ();
3806
- I != E && !HasInAllocaArgs; ++I)
3807
- HasInAllocaArgs = isInAllocaArgument (CGM.getCXXABI (), *I);
3808
- if (HasInAllocaArgs) {
3809
- assert (getTarget ().getTriple ().getArch () == llvm::Triple::x86);
3810
- Args.allocateArgumentMemory (*this );
3811
- }
3898
+ if (hasInAllocaArgs (CGM, ExplicitCC, ArgTypes)) {
3899
+ assert (getTarget ().getTriple ().getArch () == llvm::Triple::x86 &&
3900
+ " inalloca only supported on x86" );
3901
+ Args.allocateArgumentMemory (*this );
3812
3902
}
3813
3903
3814
3904
// Evaluate each argument in the appropriate order.
0 commit comments