Index: include/clang/Basic/LangOptions.h =================================================================== --- include/clang/Basic/LangOptions.h +++ include/clang/Basic/LangOptions.h @@ -65,6 +65,14 @@ PPTMK_FullGeneralityVirtualInheritance }; + enum DefaultMSCallingConvention { + DCC_None, + DCC_CDecl, + DCC_FastCall, + DCC_StdCall, + DCC_VectorCall + }; + enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; enum MSVCMajorVersion { Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -172,6 +172,7 @@ LANGOPT(CharIsSigned , 1, 1, "signed char") LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t") ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method") +ENUM_LANGOPT(DefaultMSCallingConv, DefaultMSCallingConvention, 3, DCC_None, "default calling convention") LANGOPT(ShortEnums , 1, 0, "short enum types") @@ -216,7 +217,6 @@ LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map") ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode") -LANGOPT(MRTD , 1, 0, "-mrtd calling convention") BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing") LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime") Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -610,6 +610,11 @@ HelpText<"Use the native __fp16 type for arguments and returns (and skip ABI-specific lowering)">; 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">; +def mrtd : Flag<["-"], "mrtd">, Group, + Alias, AliasArgs<["stdcall"]>, + HelpText<"Make StdCall the default calling convention">; // C++ TSes. def fcoroutines : Flag<["-"], "fcoroutines">, Index: include/clang/Driver/CLCompatOptions.td =================================================================== --- include/clang/Driver/CLCompatOptions.td +++ include/clang/Driver/CLCompatOptions.td @@ -268,6 +268,15 @@ def _SLASH_Fp : CLJoined<"Fp">, HelpText<"Set pch filename (with /Yc and /Yu)">, MetaVarName<"">; +def _SLASH_Gd : CLFlag<"Gd">, + HelpText<"Set __cdecl as a default calling convention">; +def _SLASH_Gr : CLFlag<"Gr">, + HelpText<"Set __fastcall as a default calling convention">; +def _SLASH_Gz : CLFlag<"Gz">, + HelpText<"Set __stdcall as a default calling convention">; +def _SLASH_Gv : CLFlag<"Gv">, + HelpText<"Set __vectorcall as a default calling convention">; + // Ignored: def _SLASH_analyze_ : CLIgnoredFlag<"analyze-">; @@ -279,7 +288,6 @@ def _SLASH_Fd : CLIgnoredJoined<"Fd">; def _SLASH_FC : CLIgnoredFlag<"FC">; def _SLASH_FS : CLIgnoredFlag<"FS">, HelpText<"Force synchronous PDB writes">; -def _SLASH_Gd : CLIgnoredFlag<"Gd">; def _SLASH_GF : CLIgnoredFlag<"GF">; def _SLASH_GS_ : CLIgnoredFlag<"GS-">; def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">; @@ -324,12 +332,9 @@ def _SLASH_GL_ : CLFlag<"GL-">; def _SLASH_Gm : CLFlag<"Gm">; def _SLASH_Gm_ : CLFlag<"Gm-">; -def _SLASH_Gr : CLFlag<"Gr">; def _SLASH_GS : CLFlag<"GS">; def _SLASH_GT : CLFlag<"GT">; def _SLASH_Guard : CLJoined<"guard:">; -def _SLASH_Gv : CLFlag<"Gv">; -def _SLASH_Gz : CLFlag<"Gz">; def _SLASH_GZ : CLFlag<"GZ">; def _SLASH_H : CLFlag<"H">; def _SLASH_homeparams : CLFlag<"homeparams">; Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1543,8 +1543,6 @@ HelpText<"(integrated-as) Emit an object file which can be used with an incremental linker">; def mno_incremental_linker_compatible : Flag<["-"], "mno-incremental-linker-compatible">, Group, HelpText<"(integrated-as) Emit an object file which cannot be used with an incremental linker">; -def mrtd : Flag<["-"], "mrtd">, Group, Flags<[CC1Option]>, - HelpText<"Make StdCall calling convention the default">; def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">, Group; def msoft_float : Flag<["-"], "msoft-float">, Group, Flags<[CC1Option]>, HelpText<"Use software floating point">; Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -8605,8 +8605,25 @@ if (IsCXXMethod) return ABI->getDefaultMethodCallConv(IsVariadic); - if (LangOpts.MRTD && !IsVariadic) return CC_X86StdCall; - + switch (LangOpts.getDefaultMSCallingConv()) { + case LangOptions::DCC_None: + break; + case LangOptions::DCC_CDecl: + return CC_C; + case LangOptions::DCC_FastCall: + if (getTargetInfo().hasFeature("sse2")) + 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; + } return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -6140,6 +6140,15 @@ CmdArgs.push_back("-fms-memptr-rep=virtual"); } + if (Args.getLastArg(options::OPT__SLASH_Gd)) + CmdArgs.push_back("-fdefault-calling-conv=cdecl"); + else if (Args.getLastArg(options::OPT__SLASH_Gr)) + CmdArgs.push_back("-fdefault-calling-conv=fastcall"); + else if (Args.getLastArg(options::OPT__SLASH_Gz)) + CmdArgs.push_back("-fdefault-calling-conv=stdcall"); + else if (Args.getLastArg(options::OPT__SLASH_Gv)) + CmdArgs.push_back("-fdefault-calling-conv=vectorcall"); + if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ)) A->render(Args, CmdArgs); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1772,7 +1772,6 @@ Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align); Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant); Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math); - Opts.MRTD = Args.hasArg(OPT_mrtd); Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat); Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); @@ -1849,6 +1848,34 @@ Opts.setMSPointerToMemberRepresentationMethod(InheritanceModel); } + // Check for MS default calling conventions being specified. + if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) { + LangOptions::DefaultMSCallingConvention DefaultCC = + llvm::StringSwitch( + A->getValue()) + .Case("cdecl", LangOptions::DCC_CDecl) + .Case("fastcall", LangOptions::DCC_FastCall) + .Case("stdcall", LangOptions::DCC_StdCall) + .Case("vectorcall", LangOptions::DCC_VectorCall) + .Default(LangOptions::DCC_None); + if (DefaultCC == LangOptions::DCC_None) + Diags.Report(diag::err_drv_invalid_value) + << "-fdefault-calling-conv=" << A->getValue(); + + llvm::Triple T(TargetOpts.Triple); + llvm::Triple::ArchType Arch = T.getArch(); + bool emitError = (DefaultCC == LangOptions::DCC_FastCall || + DefaultCC == LangOptions::DCC_StdCall) && + Arch != llvm::Triple::x86; + emitError |= DefaultCC == LangOptions::DCC_VectorCall && + !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); + if (emitError) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getSpelling() << T.getTriple(); + else + Opts.setDefaultMSCallingConv(DefaultCC); + } + // Check if -fopenmp is specified. Opts.OpenMP = Args.hasArg(options::OPT_fopenmp); Opts.OpenMPUseTLS = Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3895,11 +3895,12 @@ // This convention is not valid for the target. Use the default function or // method calling convention. - TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; - if (FD) - MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : - TargetInfo::CCMT_NonMember; - CC = TI.getDefaultCallingConv(MT); + bool isCXXMethod = false, isVariadic = false; + if (FD) { + isCXXMethod = FD->isCXXInstanceMember(); + isVariadic = FD->isVariadic(); + } + CC = Context.getDefaultCallingConvention(isVariadic, isCXXMethod); } attr.setProcessingCache((unsigned) CC); Index: test/CodeGenCXX/default_calling_conv.cpp =================================================================== --- test/CodeGenCXX/default_calling_conv.cpp +++ test/CodeGenCXX/default_calling_conv.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fdefault-calling-conv=cdecl -emit-llvm -o - %s | FileCheck %s --check-prefix=CDECL --check-prefix=ALL +// RUN: %clang_cc1 -triple i786-unknown-linux-gnu -target-feature +sse4.2 -fdefault-calling-conv=fastcall -emit-llvm -o - %s | FileCheck %s --check-prefix=FASTCALL --check-prefix=ALL +// 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 + +// CDECL: define void @_Z5test1v +// FASTCALL: define x86_fastcallcc void @_Z5test1v +// STDCALL: define x86_stdcallcc void @_Z5test1v +// VECTORCALL: define x86_vectorcallcc void @_Z5test1v +void test1() {} + +// ALL: define void @_Z5test2v +void __attribute__((cdecl)) test2() {} + +// ALL: define x86_fastcallcc void @_Z5test3v +void __attribute__((fastcall)) test3() {} + +// ALL: define x86_stdcallcc void @_Z5test4v +void __attribute__((stdcall)) test4() {} + +// ALL: define x86_vectorcallcc void @_Z5test5v +void __attribute__((vectorcall)) test5() {} + +// ALL: define linkonce_odr void @_ZN1A11test_memberEv +class A { +public: + void test_member() {} +}; + +void test() { + A a; + a.test_member(); +}