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,16 @@ return TargetInfo::VoidPtrBuiltinVaList; } +TargetInfo::CallingConvCheckResult +M68kTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + case CC_C: + // The M68k_RTD calling convention. + case CC_X86StdCall: + 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 @@ -48,7 +48,10 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { switch (CC) { default: return llvm::CallingConv::C; - case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; + case CC_X86StdCall: + return CGM.getTriple().getArch() == llvm::Triple::m68k + ? llvm::CallingConv::M68k_RTD + : llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; case CC_X86RegCall: return llvm::CallingConv::X86_RegCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -553,9 +553,10 @@ if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) { auto DefaultCC = LangOpts.getDefaultCallingConv(); - bool emitError = (DefaultCC == LangOptions::DCC_FastCall || - DefaultCC == LangOptions::DCC_StdCall) && - Arch != llvm::Triple::x86; + bool emitError = + DefaultCC == LangOptions::DCC_FastCall && Arch != llvm::Triple::x86; + emitError |= DefaultCC == LangOptions::DCC_StdCall && + !(Arch == llvm::Triple::m68k || Arch == llvm::Triple::x86); emitError |= (DefaultCC == LangOptions::DCC_VectorCall || DefaultCC == LangOptions::DCC_RegCall) && !T.isX86(); @@ -3747,7 +3748,7 @@ Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << "-fdefault-calling-conv"; else { - if (T.getArch() != llvm::Triple::x86) + if (T.getArch() != llvm::Triple::x86 && T.getArch() != llvm::Triple::m68k) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple(); else Index: clang/test/CodeGen/mrtd.c =================================================================== --- clang/test/CodeGen/mrtd.c +++ clang/test/CodeGen/mrtd.c @@ -1,20 +1,26 @@ -// RUN: %clang_cc1 -mrtd -triple i386-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck %s +// 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 -// CHECK: mrtd.c:10:3: warning: function with no prototype cannot use the stdcall calling convention +// CHECK: mrtd.c:13:3: warning: function with no prototype cannot use the stdcall calling convention 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{{.*}} cc104 void @foo(i32 noundef %arg) void foo(int arg) { -// CHECK: call x86_stdcallcc i32 @bar( +// X86: call x86_stdcallcc i32 @bar( +// M68k: call cc104 i32 @bar( bar(arg); -// CHECK: call x86_stdcallcc void @baz(i32 +// X86: call x86_stdcallcc void @baz(i32 +// M68k: call cc104 void @baz(i32 baz(arg); } -// CHECK: declare x86_stdcallcc i32 @bar(...) +// X86: declare x86_stdcallcc i32 @bar(...) +// M68k: declare cc104 i32 @bar(...) -// CHECK: declare x86_stdcallcc void @baz(i32 noundef) +// X86: declare x86_stdcallcc void @baz(i32 noundef) +// M68k: declare cc104 void @baz(i32 noundef) void qux(int arg, ...) { } // CHECK: define{{.*}} void @qux(i32 noundef %arg, ...) @@ -22,7 +28,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{{.*}} cc104 void @quux // CHECK: call void (i32, ...) @qux -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// X86: attributes [[NUW]] = { noinline nounwind{{.*}} } Index: clang/test/Sema/mrtd.c =================================================================== --- clang/test/Sema/mrtd.c +++ clang/test/Sema/mrtd.c @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -DMRTD -mrtd -triple i386-unknown-unknown -verify %s +// RUN: %clang_cc1 -DMRTD -mrtd -triple m68k-unknown-unknown -verify %s // RUN: %clang_cc1 -triple i386-unknown-unknown -verify %s +// RUN: %clang_cc1 -triple m68k-unknown-unknown -verify %s #ifndef MRTD // expected-note@+5 {{previous declaration is here}}