[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