Ensure builtins use the target default Calling Convention

r355317 changed builtins/allocation functions to use the default calling
convention in order to support platforms that use non-cdecl calling
conventions by default.

However the default calling convention is overridable on Windows 32 bit
implementations with some of the /G options. The intent is to permit the
user to set the calling convention of normal functions, however it
should NOT apply to builtins and C++ allocation functions.

This patch ensures that the builtin/allocation functions always use the
Target specific Calling Convention, ignoring the user overridden version
of said default.

llvm-svn: 361507
This commit is contained in:
Erich Keane 2019-05-23 16:05:21 +00:00
parent 6aebd8394a
commit 000228183b
4 changed files with 45 additions and 28 deletions

View File

@ -2395,7 +2395,8 @@ public:
/// Retrieves the default calling convention for the current target.
CallingConv getDefaultCallingConvention(bool IsVariadic,
bool IsCXXMethod) const;
bool IsCXXMethod,
bool IsBuiltin = false) const;
/// Retrieves the "canonical" template name that refers to a
/// given template.

View File

@ -9627,8 +9627,8 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
bool Variadic = (TypeStr[0] == '.');
FunctionType::ExtInfo EI(
getDefaultCallingConvention(Variadic, /*IsCXXMethod=*/false));
FunctionType::ExtInfo EI(getDefaultCallingConvention(
Variadic, /*IsCXXMethod=*/false, /*IsBuiltin=*/true));
if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true);
@ -10005,34 +10005,39 @@ void ASTContext::forEachMultiversionedFunctionVersion(
}
CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
bool IsCXXMethod) const {
bool IsCXXMethod,
bool IsBuiltin) const {
// Pass through to the C++ ABI object
if (IsCXXMethod)
return ABI->getDefaultMethodCallConv(IsVariadic);
switch (LangOpts.getDefaultCallingConv()) {
case LangOptions::DCC_None:
break;
case LangOptions::DCC_CDecl:
return CC_C;
case LangOptions::DCC_FastCall:
if (getTargetInfo().hasFeature("sse2") && !IsVariadic)
return CC_X86FastCall;
break;
case LangOptions::DCC_StdCall:
if (!IsVariadic)
return CC_X86StdCall;
break;
case LangOptions::DCC_VectorCall:
// __vectorcall cannot be applied to variadic functions.
if (!IsVariadic)
return CC_X86VectorCall;
break;
case LangOptions::DCC_RegCall:
// __regcall cannot be applied to variadic functions.
if (!IsVariadic)
return CC_X86RegCall;
break;
// Builtins ignore user-specified default calling convention and remain the
// Target's default calling convention.
if (!IsBuiltin) {
switch (LangOpts.getDefaultCallingConv()) {
case LangOptions::DCC_None:
break;
case LangOptions::DCC_CDecl:
return CC_C;
case LangOptions::DCC_FastCall:
if (getTargetInfo().hasFeature("sse2") && !IsVariadic)
return CC_X86FastCall;
break;
case LangOptions::DCC_StdCall:
if (!IsVariadic)
return CC_X86StdCall;
break;
case LangOptions::DCC_VectorCall:
// __vectorcall cannot be applied to variadic functions.
if (!IsVariadic)
return CC_X86VectorCall;
break;
case LangOptions::DCC_RegCall:
// __regcall cannot be applied to variadic functions.
if (!IsVariadic)
return CC_X86RegCall;
break;
}
}
return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown);
}

View File

@ -2816,7 +2816,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
}
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
/*IsVariadic=*/false, /*IsCXXMethod=*/false));
/*IsVariadic=*/false, /*IsCXXMethod=*/false, /*IsBuiltin=*/true));
QualType BadAllocType;
bool HasBadAllocExceptionSpec

View File

@ -2,6 +2,7 @@
// RUN: %clang_cc1 -triple spir-unknown-unknown -DREDECL -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR
// RUN: %clang_cc1 -triple x86_64-linux-pc -emit-llvm %s -o - | FileCheck %s -check-prefix LINUX
// RUN: %clang_cc1 -triple spir-unknown-unknown -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR
// RUN: %clang_cc1 -triple i386-windows-pc -fdefault-calling-conv=stdcall -emit-llvm %s -o - | FileCheck %s -check-prefix WIN32
#ifdef REDECL
namespace std {
@ -40,3 +41,13 @@ void user() {
// SPIR: declare spir_func noalias i8* @_Znwj(i32)
// SPIR: declare spir_func float @atan2f(float, float)
// SPIR: declare spir_func void @_Z3foov()
// Note: Windows /G options should not change the platform default calling
// convention of builtins.
// WIN32: define dso_local x86_stdcallcc void @"?user@@YGXXZ"()
// WIN32: call i8* @"??2@YAPAXI@Z"
// WIN32: call float @atan2f
// WIN32: call x86_stdcallcc void @"?foo@@YGXXZ"
// WIN32: declare dso_local noalias i8* @"??2@YAPAXI@Z"(
// WIN32: declare dso_local float @atan2f(float, float)
// WIN32: declare dso_local x86_stdcallcc void @"?foo@@YGXXZ"()