From dd43cfced871556930bf258c325bc29e88ca932c Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 23 May 2019 16:05:21 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@361507 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 3 +- lib/AST/ASTContext.cpp | 57 +++++++++++++----------- lib/Sema/SemaExprCXX.cpp | 2 +- test/CodeGenCXX/builtin-calling-conv.cpp | 11 +++++ 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 5cb4a82ced..6856cb6585 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 71745042fd..c3a09723ef 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 87dc3a9a54..455a71bd0a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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 diff --git a/test/CodeGenCXX/builtin-calling-conv.cpp b/test/CodeGenCXX/builtin-calling-conv.cpp index 6fdeca0d2c..f7759e3e8c 100644 --- a/test/CodeGenCXX/builtin-calling-conv.cpp +++ b/test/CodeGenCXX/builtin-calling-conv.cpp @@ -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"() -- 2.50.1