[clang] fd4f962 - [Clang][M68k] Add Clang support for the new M68k_RTD CC

Min-Yih Hsu via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 15 16:14:55 PDT 2023


Author: Min-Yih Hsu
Date: 2023-10-15T16:13:43-07:00
New Revision: fd4f96290ac99bf8b9284d3b32743cac0bb135ea

URL: https://github.com/llvm/llvm-project/commit/fd4f96290ac99bf8b9284d3b32743cac0bb135ea
DIFF: https://github.com/llvm/llvm-project/commit/fd4f96290ac99bf8b9284d3b32743cac0bb135ea.diff

LOG: [Clang][M68k] Add Clang support for the new M68k_RTD CC

This patch adds `CC_M68kRTD`, which will be used on function if either
`__attribute__((m68k_rtd))` is presented or `-mrtd` flag is given.

Differential Revision: https://reviews.llvm.org/D149867

Added: 
    clang/test/CodeGenCXX/m68k-rtdcall.cpp
    clang/test/Sema/m68k-rtdcall.c
    clang/test/SemaCXX/m68k-rtdcall.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang-c/Index.h
    clang/include/clang/Basic/Attr.td
    clang/include/clang/Basic/AttrDocs.td
    clang/include/clang/Basic/LangOptions.h
    clang/include/clang/Basic/Specifiers.h
    clang/include/clang/Driver/Options.td
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/ItaniumMangle.cpp
    clang/lib/AST/Type.cpp
    clang/lib/AST/TypePrinter.cpp
    clang/lib/Basic/Targets/M68k.cpp
    clang/lib/Basic/Targets/M68k.h
    clang/lib/CodeGen/CGCall.cpp
    clang/lib/CodeGen/CGDebugInfo.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Frontend/CompilerInvocation.cpp
    clang/lib/Sema/SemaDeclAttr.cpp
    clang/lib/Sema/SemaType.cpp
    clang/test/CodeGen/mrtd.c
    clang/test/CodeGenCXX/default_calling_conv.cpp
    clang/tools/libclang/CXType.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index be7c8bf247f7af5..6d315e9f84ddfe8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -205,6 +205,10 @@ Modified Compiler Flags
 * ``-frewrite-includes`` now guards the original #include directives with
   ``__CLANG_REWRITTEN_INCLUDES``, and ``__CLANG_REWRITTEN_SYSTEM_INCLUDES`` as
   appropriate.
+* 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
 -------------------------

diff  --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 1b91feabd584c50..64ab3378957c702 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2980,6 +2980,7 @@ enum CXCallingConv {
   CXCallingConv_AArch64VectorCall = 16,
   CXCallingConv_SwiftAsync = 17,
   CXCallingConv_AArch64SVEPCS = 18,
+  CXCallingConv_M68kRTD = 19,
 
   CXCallingConv_Invalid = 100,
   CXCallingConv_Unexposed = 200

diff  --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 5c9eb7b8a981037..5486b36133755cc 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2805,6 +2805,11 @@ def PreserveAll : DeclOrTypeAttr {
   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">];

diff  --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 9f9991bdae36155..cbbf69faeb308ad 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -2825,6 +2825,18 @@ See the documentation for `__vectorcall`_ on MSDN for more details.
   }];
 }
 
+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

diff  --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index e0e95f6d26f4545..20a8ada60e0fe51 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -134,7 +134,8 @@ class LangOptions : public LangOptionsBase {
     DCC_FastCall,
     DCC_StdCall,
     DCC_VectorCall,
-    DCC_RegCall
+    DCC_RegCall,
+    DCC_RtdCall
   };
 
   enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };

diff  --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 6ae56703eca4127..0add24d53b21e34 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -288,6 +288,7 @@ namespace clang {
     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 @@ namespace clang {
     case CC_OpenCLKernel:
     case CC_Swift:
     case CC_SwiftAsync:
+    case CC_M68kRTD:
       return false;
     default:
       return true;

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3f2058a5d4650ca..54afd652ad3d0fe 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -7478,9 +7478,9 @@ def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and
   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<LangOpts<"DefaultCallingConv">, "DCC_None">;
 
 // These options cannot be marshalled, because they are used to set up the LangOptions defaults.

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index cdc3d62bca00873..4c4bcbf8a68f7ff 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -12024,6 +12024,10 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic,
       if (!IsVariadic)
         return CC_X86RegCall;
       break;
+    case LangOptions::DCC_RtdCall:
+      if (!IsVariadic)
+        return CC_M68kRTD;
+      break;
     }
   }
   return Target->getDefaultCallingConv();

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 23ec35cae4b7b40..8862f4d4fbd7bf9 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3429,6 +3429,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
   case CC_OpenCLKernel:
   case CC_PreserveMost:
   case CC_PreserveAll:
+  case CC_M68kRTD:
     // FIXME: we should be mangling all of the above.
     return "";
 

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 282298971705ba0..570d460edbda0f9 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3373,6 +3373,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
   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.");
@@ -3852,6 +3853,7 @@ bool AttributedType::isCallingConv() const {
   case attr::IntelOclBicc:
   case attr::PreserveMost:
   case attr::PreserveAll:
+  case attr::M68kRTD:
     return true;
   }
   llvm_unreachable("invalid attr kind");

diff  --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index eb69d0bb8755b48..b9f6c0eeb450d2c 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1044,6 +1044,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
     case CC_PreserveAll:
       OS << " __attribute__((preserve_all))";
       break;
+    case CC_M68kRTD:
+      OS << " __attribute__((m68k_rtd))";
+      break;
     }
   }
 
@@ -1879,6 +1882,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
   case attr::PreserveAll:
     OS << "preserve_all";
     break;
+  case attr::M68kRTD:
+    OS << "m68k_rtd";
+    break;
   case attr::NoDeref:
     OS << "noderef";
     break;

diff  --git a/clang/lib/Basic/Targets/M68k.cpp b/clang/lib/Basic/Targets/M68k.cpp
index 3c6274f89dab162..1b7e0a7f32c9be5 100644
--- a/clang/lib/Basic/Targets/M68k.cpp
+++ b/clang/lib/Basic/Targets/M68k.cpp
@@ -238,5 +238,15 @@ TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
   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

diff  --git a/clang/lib/Basic/Targets/M68k.h b/clang/lib/Basic/Targets/M68k.h
index 1af00115a5059a5..a9c262e62fbad0b 100644
--- a/clang/lib/Basic/Targets/M68k.h
+++ b/clang/lib/Basic/Targets/M68k.h
@@ -54,6 +54,7 @@ class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
   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

diff  --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 93e16575042c4da..150450e9165900f 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -72,6 +72,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   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;
   }
 }
 
@@ -252,6 +253,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
   if (D->hasAttr<PreserveAllAttr>())
     return CC_PreserveAll;
 
+  if (D->hasAttr<M68kRTDAttr>())
+    return CC_M68kRTD;
+
   return CC_C;
 }
 

diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index c73a63e12f03aab..c430713b0d77d79 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1445,6 +1445,8 @@ static unsigned getDwarfCC(CallingConv CC) {
     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;
 }

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b91126ebed0186c..94c184435ae14de 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5466,8 +5466,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
-  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.

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index bb442495f58359c..4e6d7bb16f51beb 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -648,6 +648,7 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
     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();
@@ -3865,11 +3866,17 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
       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);
+      }
     }
   }
 

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index feb02cad9080e3e..5adf058bea56a53 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5211,6 +5211,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   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");
   }
@@ -5408,6 +5411,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
   case ParsedAttr::AT_PreserveAll:
     CC = CC_PreserveAll;
     break;
+  case ParsedAttr::AT_M68kRTD:
+    CC = CC_M68kRTD;
+    break;
   default: llvm_unreachable("unexpected attribute kind");
   }
 
@@ -9353,6 +9359,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   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:

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 068971f8130a4aa..2182fa6f7550c07 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -136,7 +136,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
   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                                           \
@@ -7802,6 +7803,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
     return createSimpleAttr<PreserveMostAttr>(Ctx, Attr);
   case ParsedAttr::AT_PreserveAll:
     return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
+  case ParsedAttr::AT_M68kRTD:
+    return createSimpleAttr<M68kRTDAttr>(Ctx, Attr);
   }
   llvm_unreachable("unexpected attribute kind!");
 }

diff  --git a/clang/test/CodeGen/mrtd.c b/clang/test/CodeGen/mrtd.c
index e615cdfa674bc79..c37a9ea95d02ae1 100644
--- a/clang/test/CodeGen/mrtd.c
+++ b/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 qux(int arg, ...) { }
 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{{.*}} }

diff  --git a/clang/test/CodeGenCXX/default_calling_conv.cpp b/clang/test/CodeGenCXX/default_calling_conv.cpp
index 0991f862b881d5c..ff81f3712116d94 100644
--- a/clang/test/CodeGenCXX/default_calling_conv.cpp
+++ b/clang/test/CodeGenCXX/default_calling_conv.cpp
@@ -1,43 +1,50 @@
-// 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
-// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=regcall -emit-llvm -o - %s | FileCheck %s --check-prefix=REGCALL --check-prefix=ALL
+// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -fdefault-calling-conv=cdecl -emit-llvm -o - %s | FileCheck %s --check-prefix=CDECL --check-prefix=X86 --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=X86 --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=X86 --check-prefix=ALL
+// RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=X86 --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=X86 --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=X86 --check-prefix=ALL
 // RUN: %clang_cc1 -triple i686-pc-win32 -fdefault-calling-conv=vectorcall -emit-llvm -o - %s -DWINDOWS | FileCheck %s --check-prefix=WIN32
 // RUN: %clang_cc1 -triple x86_64-windows-msvc -fdefault-calling-conv=vectorcall -emit-llvm -o - %s -DWINDOWS | FileCheck %s --check-prefix=WIN64
 // RUN: %clang_cc1 -triple i686-pc-win32 -emit-llvm -o - %s -DEXPLICITCC | FileCheck %s --check-prefix=EXPLICITCC
+// RUN: %clang_cc1 -triple m68k-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=RTDCALL --check-prefix=ALL
+// RUN: %clang_cc1 -triple m68k-unknown-linux-gnu -fdefault-calling-conv=rtdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=RTDCALL --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
+// RTDCALL: define{{.*}} m68k_rtdcc void @_Z5test1v
 void test1() {}
 
-// fastcall, stdcall, vectorcall and regcall do not support variadic functions.
+// fastcall, stdcall, vectorcall, regcall and m68k_rtd do not support variadic functions.
 // CDECL: define{{.*}} void @_Z12testVariadicz
 // FASTCALL: define{{.*}} void @_Z12testVariadicz
 // STDCALL: define{{.*}} void @_Z12testVariadicz
 // VECTORCALL: define{{.*}} void @_Z12testVariadicz
 // REGCALL: define{{.*}} void @_Z12testVariadicz
+// RTDCALL: define{{.*}} void @_Z12testVariadicz
 void testVariadic(...){}
 
-// ALL: define{{.*}} void @_Z5test2v
+// X86: define{{.*}} void @_Z5test2v
 void __attribute__((cdecl)) test2() {}
 
-// ALL: define{{.*}} x86_fastcallcc void @_Z5test3v
+// X86: define{{.*}} x86_fastcallcc void @_Z5test3v
 void __attribute__((fastcall)) test3() {}
 
-// ALL: define{{.*}} x86_stdcallcc void @_Z5test4v
+// X86: define{{.*}} x86_stdcallcc void @_Z5test4v
 void __attribute__((stdcall)) test4() {}
 
-// ALL: define{{.*}} x86_vectorcallcc void @_Z5test5v
+// X86: define{{.*}} x86_vectorcallcc void @_Z5test5v
 void __attribute__((vectorcall)) test5() {}
 
-// ALL: define{{.*}} x86_regcallcc void @_Z17__regcall3__test6v
+// X86: define{{.*}} x86_regcallcc void @_Z17__regcall3__test6v
 void __attribute__((regcall)) test6() {}
 
+// RTDCALL: define{{.*}} m68k_rtdcc void @_Z5test7v
+void __attribute__((m68k_rtd)) test7() {}
+
 // ALL: define linkonce_odr void @_ZN1A11test_memberEv
 class A {
 public:
@@ -47,6 +54,10 @@ class A {
 void test() {
   A a;
   a.test_member();
+
+// ALL: define internal void @"_ZZ{{.*}}testvENK3$_0clEi"
+  auto f = [](int b) {};
+  f(87);
 }
 
 // ALL: define{{.*}} i32 @main

diff  --git a/clang/test/CodeGenCXX/m68k-rtdcall.cpp b/clang/test/CodeGenCXX/m68k-rtdcall.cpp
new file mode 100644
index 000000000000000..835649359ae1517
--- /dev/null
+++ b/clang/test/CodeGenCXX/m68k-rtdcall.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple m68k-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+class A {
+public:
+// CHECK: define{{.*}} m68k_rtdcc void @_ZN1A6memberEv
+  void __attribute__((m68k_rtd)) member() {}
+};
+
+void test() {
+  A a;
+  a.member();
+
+// CHECK: define{{.*}} m68k_rtdcc void @"_ZZ4testvENK3$_0clEi"
+  auto f = [](int b) __attribute__((m68k_rtd)) {};
+  f(87);
+};

diff  --git a/clang/test/Sema/m68k-rtdcall.c b/clang/test/Sema/m68k-rtdcall.c
new file mode 100644
index 000000000000000..114af64aaa5a751
--- /dev/null
+++ b/clang/test/Sema/m68k-rtdcall.c
@@ -0,0 +1,46 @@
+// 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 at +2 {{function with no prototype cannot use the m68k_rtd calling convention}}
+void foo(int arg) {
+  bar(arg);
+}
+
+// nortd-note at +4 {{previous declaration is here}}
+// nortd-error at +4 {{function declared 'm68k_rtd' here was previously declared without calling convention}}
+// nortd-note at +4 {{previous declaration is here}}
+// nortd-error at +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 at +2 {{variadic function cannot use m68k_rtd calling convention}}
+void variadic(int a, ...);
+void __attribute__((m68k_rtd)) variadic(int a, ...);
+
+// rtd-note at +2 {{previous declaration is here}}
+// rtd-error at +2 {{redeclaration of 'a' with a 
diff erent 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 at +2 {{previous declaration is here}}
+// nortd-error at +2 {{redeclaration of 'c' with a 
diff erent 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 at +2 {{variadic function cannot use m68k_rtd calling convention}}
+extern void (*d)(int, ...);
+__attribute__((m68k_rtd)) extern void (*d)(int, ...);
+
+// expected-warning at +1 {{'m68k_rtd' only applies to function types; type here is 'int'}}
+__attribute__((m68k_rtd)) static int g = 0;
+
+// expected-error at +1 {{'m68k_rtd' attribute takes no arguments}}
+void __attribute__((m68k_rtd("invalid"))) z(int a);
+
+// expected-error at +1 {{function with no prototype cannot use the m68k_rtd calling convention}}
+void __attribute__((m68k_rtd)) e();

diff  --git a/clang/test/SemaCXX/m68k-rtdcall.cpp b/clang/test/SemaCXX/m68k-rtdcall.cpp
new file mode 100644
index 000000000000000..31f4bceafd95524
--- /dev/null
+++ b/clang/test/SemaCXX/m68k-rtdcall.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple m68k-linux-gnu -fsyntax-only %s
+
+class A {
+public:
+  void __attribute__((m68k_rtd)) member() {}
+};
+
+void test() {
+  A a;
+  a.member();
+
+  auto f = [](int b) __attribute__((m68k_rtd)) {};
+  f(87);
+};

diff  --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index eb8bfc25a7c9106..3d620d3bfb2602b 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -678,6 +678,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
       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;


        


More information about the cfe-commits mailing list