Skip to content

Commit df28221

Browse files
committed
Don't setup inalloca for swiftcc on i686-windows-msvc
Swiftcall does it's own target-independent argument type classification, since it is not designed to be ABI compatible with anything local on the target that isn't LLVM-based. This means it never uses inalloca. However, we have duplicate logic for checking for inalloca parameters that runs before call argument setup. This logic needs to know ahead of time if inalloca will be used later, and we can't move the CGFunctionInfo calculation earlier. This change gets the calling convention from either the FunctionProtoType or ObjCMethodDecl, checks if it is swift, and if so skips the stackbase setup. Depends on D92883. Differential Revision: https://reviews.llvm.org/D92944
1 parent d7098ff commit df28221

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) {
198198
FTP);
199199
}
200200

201-
static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
201+
static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
202+
bool IsWindows) {
202203
// Set the appropriate calling convention for the Function.
203204
if (D->hasAttr<StdCallAttr>())
204205
return CC_X86StdCall;
@@ -3818,6 +3819,24 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
38183819
EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
38193820
}
38203821

3822+
// Check if the call is going to use the inalloca convention. This needs to
3823+
// agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged
3824+
// later, so we can't check it directly.
3825+
static bool hasInAllocaArgs(CodeGenModule &CGM, CallingConv ExplicitCC,
3826+
ArrayRef<QualType> ArgTypes) {
3827+
// The Swift calling convention doesn't go through the target-specific
3828+
// argument classification, so it never uses inalloca.
3829+
// TODO: Consider limiting inalloca use to only calling conventions supported
3830+
// by MSVC.
3831+
if (ExplicitCC == CC_Swift)
3832+
return false;
3833+
if (!CGM.getTarget().getCXXABI().isMicrosoft())
3834+
return false;
3835+
return llvm::any_of(ArgTypes, [&](QualType Ty) {
3836+
return isInAllocaArgument(CGM.getCXXABI(), Ty);
3837+
});
3838+
}
3839+
38213840
#ifndef NDEBUG
38223841
// Determine whether the given argument is an Objective-C method
38233842
// that may have type parameters in its signature.
@@ -3845,17 +3864,27 @@ void CodeGenFunction::EmitCallArgs(
38453864
assert((ParamsToSkip == 0 || Prototype.P) &&
38463865
"Can't skip parameters if type info is not provided");
38473866

3848-
// First, use the argument types that the type info knows about
3867+
// This variable only captures *explicitly* written conventions, not those
3868+
// applied by default via command line flags or target defaults, such as
3869+
// thiscall, aapcs, stdcall via -mrtd, etc. Computing that correctly would
3870+
// require knowing if this is a C++ instance method or being able to see
3871+
// unprototyped FunctionTypes.
3872+
CallingConv ExplicitCC = CC_C;
3873+
3874+
// First, if a prototype was provided, use those argument types.
38493875
bool IsVariadic = false;
38503876
if (Prototype.P) {
38513877
const auto *MD = Prototype.P.dyn_cast<const ObjCMethodDecl *>();
38523878
if (MD) {
38533879
IsVariadic = MD->isVariadic();
3880+
ExplicitCC = getCallingConventionForDecl(
3881+
MD, CGM.getTarget().getTriple().isOSWindows());
38543882
ArgTypes.assign(MD->param_type_begin() + ParamsToSkip,
38553883
MD->param_type_end());
38563884
} else {
38573885
const auto *FPT = Prototype.P.get<const FunctionProtoType *>();
38583886
IsVariadic = FPT->isVariadic();
3887+
ExplicitCC = FPT->getExtInfo().getCC();
38593888
ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip,
38603889
FPT->param_type_end());
38613890
}
@@ -3923,15 +3952,10 @@ void CodeGenFunction::EmitCallArgs(
39233952
};
39243953

39253954
// Insert a stack save if we're going to need any inalloca args.
3926-
bool HasInAllocaArgs = false;
3927-
if (CGM.getTarget().getCXXABI().isMicrosoft()) {
3928-
for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end();
3929-
I != E && !HasInAllocaArgs; ++I)
3930-
HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I);
3931-
if (HasInAllocaArgs) {
3932-
assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
3933-
Args.allocateArgumentMemory(*this);
3934-
}
3955+
if (hasInAllocaArgs(CGM, ExplicitCC, ArgTypes)) {
3956+
assert(getTarget().getTriple().getArch() == llvm::Triple::x86 &&
3957+
"inalloca only supported on x86");
3958+
Args.allocateArgumentMemory(*this);
39353959
}
39363960

39373961
// Evaluate each argument in the appropriate order.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-windows -emit-llvm -target-cpu core2 -o - %s | FileCheck %s
2+
3+
#define SWIFTCALL __attribute__((swiftcall))
4+
#define OUT __attribute__((swift_indirect_result))
5+
#define ERROR __attribute__((swift_error_result))
6+
#define CONTEXT __attribute__((swift_context))
7+
8+
/*****************************************************************************/
9+
/****************************** PARAMETER ABIS *******************************/
10+
/*****************************************************************************/
11+
12+
// Swift doesn't use inalloca like windows x86 normally does.
13+
struct NonTrivial {
14+
NonTrivial();
15+
NonTrivial(const NonTrivial &);
16+
int o;
17+
};
18+
19+
SWIFTCALL int receiveNonTrivial(NonTrivial o) { return o.o; }
20+
21+
// CHECK-LABEL: define dso_local swiftcc i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(%struct.NonTrivial* %o)
22+
23+
int passNonTrivial() {
24+
return receiveNonTrivial({});
25+
}
26+
27+
// CHECK-LABEL: define dso_local i32 @"?passNonTrivial@@YAHXZ"()
28+
// CHECK-NOT: stacksave
29+
// CHECK: call swiftcc i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(%struct.NonTrivial* %{{.*}})

0 commit comments

Comments
 (0)