eandrews created this revision.

Added support for regcall as default calling convention.  Also added code to 
exclude main when applying default calling conventions.


https://reviews.llvm.org/D39210

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/LangOptions.h
  include/clang/Driver/CC1Options.td
  include/clang/Driver/CLCompatOptions.td
  lib/AST/ASTContext.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Sema/SemaType.cpp
  test/CodeGenCXX/default_calling_conv.cpp
  test/Driver/cl-cc-flags.c

Index: test/Driver/cl-cc-flags.c
===================================================================
--- test/Driver/cl-cc-flags.c
+++ test/Driver/cl-cc-flags.c
@@ -13,6 +13,9 @@
 // RUN: %clang_cl --target=i686-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=VECTORCALL %s
 // VECTORCALL: -fdefault-calling-conv=vectorcall
 
+// RUN: %clang_cl --target=i686-windows-msvc /Gregcall -### -- %s 2>&1 | FileCheck --check-prefix=REGCALL %s
+// REGCALL: -fdefault-calling-conv=regcall
+
 // Last one should win:
 
 // RUN: %clang_cl --target=i686-windows-msvc /Gd /Gv -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_VECTOR %s
Index: test/CodeGenCXX/default_calling_conv.cpp
===================================================================
--- test/CodeGenCXX/default_calling_conv.cpp
+++ test/CodeGenCXX/default_calling_conv.cpp
@@ -3,11 +3,13 @@
 // RUN: %clang_cc1 -triple i486-unknown-linux-gnu -fdefault-calling-conv=stdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL
 // RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL
 // RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=vectorcall -emit-llvm -o - %s | FileCheck %s --check-prefix=VECTORCALL --check-prefix=ALL
+// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=regcall -emit-llvm -o - %s | FileCheck %s --check-prefix=REGCALL --check-prefix=ALL
 
 // CDECL: define void @_Z5test1v
 // FASTCALL: define x86_fastcallcc void @_Z5test1v
 // STDCALL: define x86_stdcallcc void @_Z5test1v
 // VECTORCALL: define x86_vectorcallcc void @_Z5test1v
+// REGCALL: define x86_regcallcc void @_Z17__regcall3__test1v
 void test1() {}
 
 // ALL: define void @_Z5test2v
@@ -22,6 +24,9 @@
 // ALL: define  x86_vectorcallcc void @_Z5test5v
 void __attribute__((vectorcall)) test5() {}
 
+// ALL: define x86_regcallcc void @_Z17__regcall3__test6v
+void __attribute__((regcall)) test6() {}
+
 // ALL: define linkonce_odr void @_ZN1A11test_memberEv
 class A {
 public:
@@ -32,3 +37,8 @@
   A a;
   a.test_member();
 }
+
+// ALL: define i32 @main
+int main() {
+  return 1;
+}
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -3266,8 +3266,14 @@
     }
   }
 
-  CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic,
-                                                         IsCXXInstanceMethod);
+  bool IsMain = false;
+  if (D.getIdentifier() && D.getIdentifier()->isStr("main") &&
+      S.CurContext->getRedeclContext()->isTranslationUnit() &&
+      !S.getLangOpts().Freestanding)
+    IsMain = true;
+
+  CallingConv CC = S.Context.getDefaultCallingConvention(
+      FTI.isVariadic, IsCXXInstanceMethod, IsMain);
 
   // Attribute AT_OpenCLKernel affects the calling convention for SPIR
   // and AMDGPU targets, hence it cannot be treated as a calling
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -2299,12 +2299,12 @@
   // Check for MS default calling conventions being specified.
   if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
     LangOptions::DefaultCallingConvention DefaultCC =
-        llvm::StringSwitch<LangOptions::DefaultCallingConvention>(
-            A->getValue())
+        llvm::StringSwitch<LangOptions::DefaultCallingConvention>(A->getValue())
             .Case("cdecl", LangOptions::DCC_CDecl)
             .Case("fastcall", LangOptions::DCC_FastCall)
             .Case("stdcall", LangOptions::DCC_StdCall)
             .Case("vectorcall", LangOptions::DCC_VectorCall)
+            .Case("regcall", LangOptions::DCC_RegCall)
             .Default(LangOptions::DCC_None);
     if (DefaultCC == LangOptions::DCC_None)
       Diags.Report(diag::err_drv_invalid_value)
@@ -2315,7 +2315,8 @@
     bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
                       DefaultCC == LangOptions::DCC_StdCall) &&
                      Arch != llvm::Triple::x86;
-    emitError |= DefaultCC == LangOptions::DCC_VectorCall &&
+    emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
+                  DefaultCC == LangOptions::DCC_RegCall) &&
                  !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64);
     if (emitError)
       Diags.Report(diag::err_drv_argument_not_allowed_with)
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -4958,7 +4958,8 @@
   // Parse the default calling convention options.
   if (Arg *CCArg =
           Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr,
-                          options::OPT__SLASH_Gz, options::OPT__SLASH_Gv)) {
+                          options::OPT__SLASH_Gz, options::OPT__SLASH_Gv,
+                          options::OPT__SLASH_Gregcall)) {
     unsigned DCCOptId = CCArg->getOption().getID();
     const char *DCCFlag = nullptr;
     bool ArchSupported = true;
@@ -4979,6 +4980,10 @@
       ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
       DCCFlag = "-fdefault-calling-conv=vectorcall";
       break;
+    case options::OPT__SLASH_Gregcall:
+      ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
+      DCCFlag = "-fdefault-calling-conv=regcall";
+      break;
     }
 
     // MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either.
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -9257,11 +9257,15 @@
 }
 
 CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
-                                                    bool IsCXXMethod) const {
+                                                    bool IsCXXMethod,
+                                                    bool IsMain) const {
   // Pass through to the C++ ABI object
   if (IsCXXMethod)
     return ABI->getDefaultMethodCallConv(IsVariadic);
 
+  if (IsMain)
+    return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown);
+
   switch (LangOpts.getDefaultCallingConv()) {
   case LangOptions::DCC_None:
     break;
@@ -9280,6 +9284,11 @@
     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);
 }
Index: include/clang/Driver/CLCompatOptions.td
===================================================================
--- include/clang/Driver/CLCompatOptions.td
+++ include/clang/Driver/CLCompatOptions.td
@@ -302,6 +302,8 @@
   HelpText<"Set __stdcall as a default calling convention">;
 def _SLASH_Gv : CLFlag<"Gv">,
   HelpText<"Set __vectorcall as a default calling convention">;
+def _SLASH_Gregcall : CLFlag<"Gregcall">,
+  HelpText<"Set __regcall as a default calling convention">;
 
 // Ignored:
 
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -704,7 +704,7 @@
 def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
   HelpText<"Allow function arguments and returns of type half">;
 def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
-  HelpText<"Set default MS calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall">;
+  HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">;
 def finclude_default_header : Flag<["-"], "finclude-default-header">,
   HelpText<"Include the default header file for OpenCL">;
 def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">,
Index: include/clang/Basic/LangOptions.h
===================================================================
--- include/clang/Basic/LangOptions.h
+++ include/clang/Basic/LangOptions.h
@@ -77,7 +77,8 @@
     DCC_CDecl,
     DCC_FastCall,
     DCC_StdCall,
-    DCC_VectorCall
+    DCC_VectorCall,
+    DCC_RegCall
   };
 
   enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -2229,8 +2229,8 @@
   getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
 
   /// \brief Retrieves the default calling convention for the current target.
-  CallingConv getDefaultCallingConvention(bool isVariadic,
-                                          bool IsCXXMethod) const;
+  CallingConv getDefaultCallingConvention(bool isVariadic, bool IsCXXMethod,
+                                          bool IsMain = false) const;
 
   /// \brief Retrieves the "canonical" template name that refers to a
   /// given template.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to