瀏覽代碼

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
Erich Keane 6 年之前
父節點
當前提交
dd43cfced8
共有 4 個文件被更改,包括 45 次插入28 次删除
  1. 2 1
      include/clang/AST/ASTContext.h
  2. 31 26
      lib/AST/ASTContext.cpp
  3. 1 1
      lib/Sema/SemaExprCXX.cpp
  4. 11 0
      test/CodeGenCXX/builtin-calling-conv.cpp

+ 2 - 1
include/clang/AST/ASTContext.h

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

+ 31 - 26
lib/AST/ASTContext.cpp

@@ -9627,8 +9627,8 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
 
 
   bool Variadic = (TypeStr[0] == '.');
   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);
   if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true);
 
 
 
 
@@ -10005,34 +10005,39 @@ void ASTContext::forEachMultiversionedFunctionVersion(
 }
 }
 
 
 CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
 CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
-                                                    bool IsCXXMethod) const {
+                                                    bool IsCXXMethod,
+                                                    bool IsBuiltin) const {
   // Pass through to the C++ ABI object
   // Pass through to the C++ ABI object
   if (IsCXXMethod)
   if (IsCXXMethod)
     return ABI->getDefaultMethodCallConv(IsVariadic);
     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);
   return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown);
 }
 }

+ 1 - 1
lib/Sema/SemaExprCXX.cpp

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

+ 11 - 0
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 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 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 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
 #ifdef REDECL
 namespace std {
 namespace std {
@@ -40,3 +41,13 @@ void user() {
 // SPIR: declare spir_func noalias i8* @_Znwj(i32)
 // SPIR: declare spir_func noalias i8* @_Znwj(i32)
 // SPIR: declare spir_func float @atan2f(float, float)
 // SPIR: declare spir_func float @atan2f(float, float)
 // SPIR: declare spir_func void @_Z3foov()
 // 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"()