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. 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/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/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: 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: 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/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( - A->getValue()) + llvm::StringSwitch(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/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: 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: 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