FTP);
}
-static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
+static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
+ bool IsWindows) {
// Set the appropriate calling convention for the Function.
if (D->hasAttr<StdCallAttr>())
return CC_X86StdCall;
EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
}
+// Check if the call is going to use the inalloca convention. This needs to
+// agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged
+// later, so we can't check it directly.
+static bool hasInAllocaArgs(CodeGenModule &CGM, CallingConv ExplicitCC,
+ ArrayRef<QualType> ArgTypes) {
+ // The Swift calling convention doesn't go through the target-specific
+ // argument classification, so it never uses inalloca.
+ // TODO: Consider limiting inalloca use to only calling conventions supported
+ // by MSVC.
+ if (ExplicitCC == CC_Swift)
+ return false;
+ if (!CGM.getTarget().getCXXABI().isMicrosoft())
+ return false;
+ return llvm::any_of(ArgTypes, [&](QualType Ty) {
+ return isInAllocaArgument(CGM.getCXXABI(), Ty);
+ });
+}
+
#ifndef NDEBUG
// Determine whether the given argument is an Objective-C method
// that may have type parameters in its signature.
assert((ParamsToSkip == 0 || Prototype.P) &&
"Can't skip parameters if type info is not provided");
- // First, use the argument types that the type info knows about
+ // This variable only captures *explicitly* written conventions, not those
+ // applied by default via command line flags or target defaults, such as
+ // thiscall, aapcs, stdcall via -mrtd, etc. Computing that correctly would
+ // require knowing if this is a C++ instance method or being able to see
+ // unprototyped FunctionTypes.
+ CallingConv ExplicitCC = CC_C;
+
+ // First, if a prototype was provided, use those argument types.
bool IsVariadic = false;
if (Prototype.P) {
const auto *MD = Prototype.P.dyn_cast<const ObjCMethodDecl *>();
if (MD) {
IsVariadic = MD->isVariadic();
+ ExplicitCC = getCallingConventionForDecl(
+ MD, CGM.getTarget().getTriple().isOSWindows());
ArgTypes.assign(MD->param_type_begin() + ParamsToSkip,
MD->param_type_end());
} else {
const auto *FPT = Prototype.P.get<const FunctionProtoType *>();
IsVariadic = FPT->isVariadic();
+ ExplicitCC = FPT->getExtInfo().getCC();
ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip,
FPT->param_type_end());
}
};
// Insert a stack save if we're going to need any inalloca args.
- bool HasInAllocaArgs = false;
- if (CGM.getTarget().getCXXABI().isMicrosoft()) {
- for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end();
- I != E && !HasInAllocaArgs; ++I)
- HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I);
- if (HasInAllocaArgs) {
- assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
- Args.allocateArgumentMemory(*this);
- }
+ if (hasInAllocaArgs(CGM, ExplicitCC, ArgTypes)) {
+ assert(getTarget().getTriple().getArch() == llvm::Triple::x86 &&
+ "inalloca only supported on x86");
+ Args.allocateArgumentMemory(*this);
}
// Evaluate each argument in the appropriate order.
--- /dev/null
+// RUN: %clang_cc1 -triple x86_64-unknown-windows -emit-llvm -target-cpu core2 -o - %s | FileCheck %s
+
+#define SWIFTCALL __attribute__((swiftcall))
+#define OUT __attribute__((swift_indirect_result))
+#define ERROR __attribute__((swift_error_result))
+#define CONTEXT __attribute__((swift_context))
+
+/*****************************************************************************/
+/****************************** PARAMETER ABIS *******************************/
+/*****************************************************************************/
+
+// Swift doesn't use inalloca like windows x86 normally does.
+struct NonTrivial {
+ NonTrivial();
+ NonTrivial(const NonTrivial &);
+ int o;
+};
+
+SWIFTCALL int receiveNonTrivial(NonTrivial o) { return o.o; }
+
+// CHECK-LABEL: define dso_local swiftcc i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(%struct.NonTrivial* %o)
+
+int passNonTrivial() {
+ return receiveNonTrivial({});
+}
+
+// CHECK-LABEL: define dso_local i32 @"?passNonTrivial@@YAHXZ"()
+// CHECK-NOT: stacksave
+// CHECK: call swiftcc i32 @"?receiveNonTrivial@@YSHUNonTrivial@@@Z"(%struct.NonTrivial* %{{.*}})