Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -247,6 +247,11 @@ directory (``/tmp`` on \*NIX systems, if none of the environment variables TMPDIR, TMP, and TEMP are specified). +- Introducing a new default calling convention for ``-fdefault-calling-conv``: + ``rtdcall``. This new default CC only works for M68k and will use the new + ``m68k_rtdcc`` CC on every functions that are not variadic. The ``-mrtd`` + driver/frontend flag has the same effect when targeting M68k. + Removed Compiler Flags ------------------------- - The deprecated flag `-fmodules-ts` is removed. Please use ``-std=c++20`` Index: clang/include/clang-c/Index.h =================================================================== --- clang/include/clang-c/Index.h +++ clang/include/clang-c/Index.h @@ -2976,6 +2976,7 @@ CXCallingConv_AArch64VectorCall = 16, CXCallingConv_SwiftAsync = 17, CXCallingConv_AArch64SVEPCS = 18, + CXCallingConv_M68kRTD = 19, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -2749,6 +2749,11 @@ let Documentation = [PreserveAllDocs]; } +def M68kRTD: DeclOrTypeAttr { + let Spellings = [Clang<"m68k_rtd">]; + let Documentation = [M68kRTDDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -2794,6 +2794,18 @@ }]; } +def M68kRTDDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On M68k targets, this attribute changes the calling convention of a function +to clear parameters off the stack on return. In other words, callee is +responsible for cleaning out the stack space allocated for incoming paramters. +This convention does not support variadic calls or unprototyped functions in C. +When targeting M68010 or newer CPUs, this calling convention is implemented +using the `rtd` instruction. + }]; +} + def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> { let Content = [{ Clang supports additional attributes for checking basic resource management Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -133,7 +133,8 @@ DCC_FastCall, DCC_StdCall, DCC_VectorCall, - DCC_RegCall + DCC_RegCall, + DCC_RtdCall }; enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; Index: clang/include/clang/Basic/Specifiers.h =================================================================== --- clang/include/clang/Basic/Specifiers.h +++ clang/include/clang/Basic/Specifiers.h @@ -288,6 +288,7 @@ CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) + CC_M68kRTD, // __attribute__((m68k_rtd)) }; /// Checks whether the given calling convention supports variadic @@ -304,6 +305,7 @@ case CC_OpenCLKernel: case CC_Swift: case CC_SwiftAsync: + case CC_M68kRTD: return false; default: return true; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -6457,9 +6457,9 @@ ImpliedByAnyOf<[open_cl.KeyPath, render_script.KeyPath, hlsl.KeyPath]>; def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, HelpText<"Set default calling convention">, - Values<"cdecl,fastcall,stdcall,vectorcall,regcall">, + Values<"cdecl,fastcall,stdcall,vectorcall,regcall,rtdcall">, NormalizedValuesScope<"LangOptions">, - NormalizedValues<["DCC_CDecl", "DCC_FastCall", "DCC_StdCall", "DCC_VectorCall", "DCC_RegCall"]>, + NormalizedValues<["DCC_CDecl", "DCC_FastCall", "DCC_StdCall", "DCC_VectorCall", "DCC_RegCall", "DCC_RtdCall"]>, MarshallingInfoEnum, "DCC_None">; // These options cannot be marshalled, because they are used to set up the LangOptions defaults. Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -12008,6 +12008,10 @@ if (!IsVariadic) return CC_X86RegCall; break; + case LangOptions::DCC_RtdCall: + if (!IsVariadic) + return CC_M68kRTD; + break; } } return Target->getDefaultCallingConv(); Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -3264,6 +3264,7 @@ case CC_OpenCLKernel: case CC_PreserveMost: case CC_PreserveAll: + case CC_M68kRTD: // FIXME: we should be mangling all of the above. return ""; Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -3350,6 +3350,7 @@ case CC_SwiftAsync: return "swiftasynccall"; case CC_PreserveMost: return "preserve_most"; case CC_PreserveAll: return "preserve_all"; + case CC_M68kRTD: return "m68k_rtd"; } llvm_unreachable("Invalid calling convention."); @@ -3818,6 +3819,7 @@ case attr::IntelOclBicc: case attr::PreserveMost: case attr::PreserveAll: + case attr::M68kRTD: return true; } llvm_unreachable("invalid attr kind"); Index: clang/lib/AST/TypePrinter.cpp =================================================================== --- clang/lib/AST/TypePrinter.cpp +++ clang/lib/AST/TypePrinter.cpp @@ -1035,6 +1035,9 @@ case CC_PreserveAll: OS << " __attribute__((preserve_all))"; break; + case CC_M68kRTD: + OS << " __attribute__((m68k_rtd))"; + break; } } @@ -1855,6 +1858,7 @@ case attr::PreserveAll: OS << "preserve_all"; break; + case attr::M68kRTD: OS << "m68k_rtd"; break; case attr::NoDeref: OS << "noderef"; break; Index: clang/lib/Basic/Targets/M68k.h =================================================================== --- clang/lib/Basic/Targets/M68k.h +++ clang/lib/Basic/Targets/M68k.h @@ -54,6 +54,7 @@ std::string_view getClobbers() const override; BuiltinVaListKind getBuiltinVaListKind() const override; bool setCPU(const std::string &Name) override; + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; }; } // namespace targets Index: clang/lib/Basic/Targets/M68k.cpp =================================================================== --- clang/lib/Basic/Targets/M68k.cpp +++ clang/lib/Basic/Targets/M68k.cpp @@ -250,5 +250,15 @@ return TargetInfo::VoidPtrBuiltinVaList; } +TargetInfo::CallingConvCheckResult +M68kTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + case CC_C: + case CC_M68kRTD: + return CCCR_OK; + default: + return TargetInfo::checkCallingConvention(CC); + } +} } // namespace targets } // namespace clang Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -70,6 +70,7 @@ case CC_PreserveAll: return llvm::CallingConv::PreserveAll; case CC_Swift: return llvm::CallingConv::Swift; case CC_SwiftAsync: return llvm::CallingConv::SwiftTail; + case CC_M68kRTD: return llvm::CallingConv::M68k_RTD; } } @@ -251,6 +252,9 @@ if (D->hasAttr()) return CC_PreserveAll; + if (D->hasAttr()) + return CC_M68kRTD; + return CC_C; } Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -1438,6 +1438,8 @@ return llvm::dwarf::DW_CC_LLVM_PreserveAll; case CC_X86RegCall: return llvm::dwarf::DW_CC_LLVM_X86RegCall; + case CC_M68kRTD: + return llvm::dwarf::DW_CC_LLVM_M68kRTD; } return 0; } Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5341,8 +5341,12 @@ } } - if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) - CmdArgs.push_back("-fdefault-calling-conv=stdcall"); + if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) { + if (Triple.getArch() == llvm::Triple::m68k) + CmdArgs.push_back("-fdefault-calling-conv=rtdcall"); + else + CmdArgs.push_back("-fdefault-calling-conv=stdcall"); + } if (Args.hasArg(options::OPT_fenable_matrix)) { // enable-matrix is needed by both the LangOpts and by LLVM. Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -559,6 +559,7 @@ emitError |= (DefaultCC == LangOptions::DCC_VectorCall || DefaultCC == LangOptions::DCC_RegCall) && !T.isX86(); + emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k; if (emitError) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple(); @@ -3779,11 +3780,17 @@ Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << "-fdefault-calling-conv"; else { - if (T.getArch() != llvm::Triple::x86) + switch (T.getArch()) { + case llvm::Triple::x86: + Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); + break; + case llvm::Triple::m68k: + Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall); + break; + default: Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple(); - else - Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); + } } } Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -5194,6 +5194,9 @@ case ParsedAttr::AT_PreserveAll: D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL)); return; + case ParsedAttr::AT_M68kRTD: + D->addAttr(::new (S.Context) M68kRTDAttr(S.Context, AL)); + return; default: llvm_unreachable("unexpected attribute kind"); } @@ -5393,6 +5396,9 @@ case ParsedAttr::AT_PreserveAll: CC = CC_PreserveAll; break; + case ParsedAttr::AT_M68kRTD: + CC = CC_M68kRTD; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -9213,6 +9219,7 @@ case ParsedAttr::AT_AArch64VectorPcs: case ParsedAttr::AT_AArch64SVEPcs: case ParsedAttr::AT_AMDGPUKernelCall: + case ParsedAttr::AT_M68kRTD: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -134,7 +134,8 @@ case ParsedAttr::AT_Pcs: \ case ParsedAttr::AT_IntelOclBicc: \ case ParsedAttr::AT_PreserveMost: \ - case ParsedAttr::AT_PreserveAll + case ParsedAttr::AT_PreserveAll: \ + case ParsedAttr::AT_M68kRTD // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ @@ -7767,6 +7768,8 @@ return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_PreserveAll: return createSimpleAttr(Ctx, Attr); + case ParsedAttr::AT_M68kRTD: + return createSimpleAttr(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } Index: clang/test/CodeGen/mrtd.c =================================================================== --- clang/test/CodeGen/mrtd.c +++ clang/test/CodeGen/mrtd.c @@ -1,20 +1,24 @@ -// RUN: %clang_cc1 -mrtd -triple i386-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck %s - -// CHECK: mrtd.c:10:3: warning: function with no prototype cannot use the stdcall calling convention +// RUN: %clang_cc1 -mrtd -triple i386-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck --check-prefixes=CHECK,X86 %s +// RUN: %clang_cc1 -mrtd -triple m68k-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck --check-prefixes=CHECK,M68k %s void baz(int arg); -// CHECK: define{{.*}} x86_stdcallcc void @foo(i32 noundef %arg) [[NUW:#[0-9]+]] +// X86: define{{.*}} x86_stdcallcc void @foo(i32 noundef %arg) [[NUW:#[0-9]+]] +// M68k: define{{.*}} m68k_rtdcc void @foo(i32 noundef %arg) void foo(int arg) { -// CHECK: call x86_stdcallcc i32 @bar( +// X86: call x86_stdcallcc i32 @bar( +#ifndef mc68000 bar(arg); -// CHECK: call x86_stdcallcc void @baz(i32 +#endif +// X86: call x86_stdcallcc void @baz(i32 +// M68k: call m68k_rtdcc void @baz(i32 baz(arg); } -// CHECK: declare x86_stdcallcc i32 @bar(...) +// X86: declare x86_stdcallcc i32 @bar(...) -// CHECK: declare x86_stdcallcc void @baz(i32 noundef) +// X86: declare x86_stdcallcc void @baz(i32 noundef) +// M68k: declare m68k_rtdcc void @baz(i32 noundef) void qux(int arg, ...) { } // CHECK: define{{.*}} void @qux(i32 noundef %arg, ...) @@ -22,7 +26,8 @@ void quux(int a1, int a2, int a3) { qux(a1, a2, a3); } -// CHECK-LABEL: define{{.*}} x86_stdcallcc void @quux +// X86-LABEL: define{{.*}} x86_stdcallcc void @quux +// M68k-LABEL: define{{.*}} m68k_rtdcc void @quux // CHECK: call void (i32, ...) @qux -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// X86: attributes [[NUW]] = { noinline nounwind{{.*}} } Index: clang/test/Sema/m68k-mrtd.c =================================================================== --- /dev/null +++ clang/test/Sema/m68k-mrtd.c @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -triple m68k-unknown-unknown -mrtd -std=c89 -verify -verify=rtd %s +// RUN: %clang_cc1 -triple m68k-unknown-unknown -std=c89 -verify -verify=nortd %s + +// rtd-error@+2 {{function with no prototype cannot use the m68k_rtd calling convention}} +void foo(int arg) { + bar(arg); +} + +// nortd-note@+4 {{previous declaration is here}} +// nortd-error@+4 {{function declared 'm68k_rtd' here was previously declared without calling convention}} +// nortd-note@+4 {{previous declaration is here}} +// nortd-error@+4 {{function declared 'm68k_rtd' here was previously declared without calling convention}} +void nonvariadic1(int a, int b, int c); +void __attribute__((m68k_rtd)) nonvariadic1(int a, int b, int c); +void nonvariadic2(int a, int b, int c); +void __attribute__((m68k_rtd)) nonvariadic2(int a, int b, int c) { } + +// expected-error@+2 {{variadic function cannot use m68k_rtd calling convention}} +void variadic(int a, ...); +void __attribute__((m68k_rtd)) variadic(int a, ...); + +// rtd-note@+2 {{previous declaration is here}} +// rtd-error@+2 {{redeclaration of 'a' with a different type: 'void ((*))(int, int) __attribute__((cdecl))' vs 'void (*)(int, int) __attribute__((m68k_rtd))'}} +extern void (*a)(int, int); +__attribute__((cdecl)) extern void (*a)(int, int); + +extern void (*b)(int, ...); +__attribute__((cdecl)) extern void (*b)(int, ...); + +// nortd-note@+2 {{previous declaration is here}} +// nortd-error@+2 {{redeclaration of 'c' with a different type: 'void ((*))(int, int) __attribute__((m68k_rtd))' vs 'void (*)(int, int)'}} +extern void (*c)(int, int); +__attribute__((m68k_rtd)) extern void (*c)(int, int); + +// expected-error@+2 {{variadic function cannot use m68k_rtd calling convention}} +extern void (*d)(int, ...); +__attribute__((m68k_rtd)) extern void (*d)(int, ...); + +// expected-warning@+1 {{'m68k_rtd' only applies to function types; type here is 'int'}} +__attribute__((m68k_rtd)) static int g = 0; + +// expected-error@+1 {{'m68k_rtd' attribute takes no arguments}} +void __attribute__((m68k_rtd("invalid"))) z(int a); Index: clang/tools/libclang/CXType.cpp =================================================================== --- clang/tools/libclang/CXType.cpp +++ clang/tools/libclang/CXType.cpp @@ -678,6 +678,7 @@ TCALLINGCONV(SwiftAsync); TCALLINGCONV(PreserveMost); TCALLINGCONV(PreserveAll); + TCALLINGCONV(M68kRTD); case CC_SpirFunction: return CXCallingConv_Unexposed; case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed; case CC_OpenCLKernel: return CXCallingConv_Unexposed;