From 4c67aa96401b67b5200e701cff87485067ab0792 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 22 Feb 2013 19:24:35 +0000 Subject: [PATCH] Add support for coldcc to clang git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175912 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LanguageExtensions.rst | 9 +++++++++ include/clang-c/Index.h | 1 + include/clang/AST/Type.h | 1 + include/clang/Basic/Attr.td | 4 ++++ include/clang/Basic/Specifiers.h | 5 +++++ include/clang/Basic/TargetInfo.h | 8 +------- lib/AST/DumpXML.cpp | 1 + lib/AST/Type.cpp | 1 + lib/AST/TypePrinter.cpp | 4 ++++ lib/Basic/Targets.cpp | 7 ++----- lib/CodeGen/CGCall.cpp | 4 ++++ lib/Sema/SemaDeclAttr.cpp | 10 ++++++++++ lib/Sema/SemaType.cpp | 3 +++ test/CodeGen/coldcc.c | 12 ++++++++++++ tools/libclang/CXType.cpp | 1 + 15 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 test/CodeGen/coldcc.c diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 014e2645d8..40459a445a 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -1970,3 +1970,12 @@ Clang implements two kinds of checks with this attribute. In this case Clang does not warn because the format string ``s`` and the corresponding arguments are annotated. If the arguments are incorrect, the caller of ``foo`` will receive a warning. + +LLVM-Specific Calling Conventions +================================= + +Clang supports `LLVM's coldcc calling convention +`_ via the ``coldcc`` +GNU-style attribute, or the ``clang::coldcc`` C++11 attribute. However, +this calling convention is not guaranteed to be ABI compatible between +different versions of the compiler. diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index c382fb17c1..12a8381ce1 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2674,6 +2674,7 @@ enum CXCallingConv { CXCallingConv_AAPCS_VFP = 7, CXCallingConv_PnaclCall = 8, CXCallingConv_IntelOclBicc = 9, + CXCallingConv_Cold = 10, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index df285101e3..2284300032 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -3323,6 +3323,7 @@ public: // No operand. attr_noreturn, attr_cdecl, + attr_coldcc, attr_fastcall, attr_stdcall, attr_thiscall, diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 70217d2beb..c3a44948b7 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -277,6 +277,10 @@ def Cold : InheritableAttr { let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">]; } +def ColdCC : InheritableAttr { + let Spellings = [GNU<"coldcc">, CXX11<"clang", "coldcc">]; +} + def Common : InheritableAttr { let Spellings = [GNU<"common">, CXX11<"gnu", "common">]; } diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 8706179a17..3f640b5261 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -188,6 +188,7 @@ namespace clang { enum CallingConv { CC_Default, CC_C, // __attribute__((cdecl)) + CC_Cold, // __attribute__((coldcc)) CC_X86StdCall, // __attribute__((stdcall)) CC_X86FastCall, // __attribute__((fastcall)) CC_X86ThisCall, // __attribute__((thiscall)) @@ -198,6 +199,10 @@ namespace clang { CC_IntelOclBicc // __attribute__((intel_ocl_bicc)) }; + inline bool isTargetSpecific(CallingConv CC) { + return CC >= CC_X86StdCall; + } + } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index deaa3eeb77..9a8689af85 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -754,13 +754,7 @@ public: /// and be substituted with the default calling convention, or (someday) /// produce an error (such as using thiscall on a non-instance function). virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { - switch (CC) { - default: - return CCCR_Warning; - case CC_C: - case CC_Default: - return CCCR_OK; - } + return CCCR_Warning; } protected: diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index be22ae450b..230f2df29c 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -925,6 +925,7 @@ struct XMLDumper : public XMLDeclVisitor, case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); case CC_PnaclCall: return set("cc", "pnaclcall"); case CC_IntelOclBicc: return set("cc", "intel_ocl_bicc"); + case CC_Cold: return set("cc", "coldcc"); } } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index efd588a57a..0cadba2749 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1547,6 +1547,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { llvm_unreachable("no name for default cc"); case CC_C: return "cdecl"; + case CC_Cold: return "coldcc"; case CC_X86StdCall: return "stdcall"; case CC_X86FastCall: return "fastcall"; case CC_X86ThisCall: return "thiscall"; diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 9d1717a220..751e298213 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -626,6 +626,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_C: OS << " __attribute__((cdecl))"; break; + case CC_Cold: + OS << " __attribute__((coldcc))"; + break; case CC_X86StdCall: OS << " __attribute__((stdcall))"; break; @@ -1156,6 +1159,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case AttributedType::attr_noreturn: OS << "noreturn"; break; case AttributedType::attr_cdecl: OS << "cdecl"; break; + case AttributedType::attr_coldcc: OS << "coldcc"; break; case AttributedType::attr_fastcall: OS << "fastcall"; break; case AttributedType::attr_stdcall: OS << "stdcall"; break; case AttributedType::attr_thiscall: OS << "thiscall"; break; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index eaf2e7d05e..bd80409bd2 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -1933,8 +1933,7 @@ public: // We accept all non-ARM calling conventions return (CC == CC_X86ThisCall || CC == CC_X86FastCall || - CC == CC_X86StdCall || - CC == CC_C || + CC == CC_X86StdCall || CC == CC_X86Pascal || CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning; } @@ -3027,9 +3026,7 @@ public: } virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { - return (CC == CC_Default || - CC == CC_C || - CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning; + return CC == CC_IntelOclBicc ? CCCR_OK : CCCR_Warning; } virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 9fd31fe253..f2c2d0a85d 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -37,6 +37,7 @@ using namespace CodeGen; static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { switch (CC) { default: return llvm::CallingConv::C; + case CC_Cold: return llvm::CallingConv::Cold; case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; @@ -135,6 +136,9 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual FTP) { static CallingConv getCallingConventionForDecl(const Decl *D) { // Set the appropriate calling convention for the Function. + if (D->hasAttr()) + return CC_Cold; + if (D->hasAttr()) return CC_X86StdCall; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 5f6f81de14..d764bee097 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3859,6 +3859,11 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { } switch (Attr.getKind()) { + case AttributeList::AT_ColdCC: + D->addAttr(::new (S.Context) + ColdCCAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); + return; case AttributeList::AT_FastCall: D->addAttr(::new (S.Context) FastCallAttr(Attr.getRange(), S.Context, @@ -3939,6 +3944,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, // move to TargetAttributesSema one day. switch (attr.getKind()) { case AttributeList::AT_CDecl: CC = CC_C; break; + case AttributeList::AT_ColdCC: CC = CC_Cold; break; case AttributeList::AT_FastCall: CC = CC_X86FastCall; break; case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break; @@ -3971,6 +3977,9 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, default: llvm_unreachable("unexpected attribute kind"); } + if (!isTargetSpecific(CC)) + return false; + const TargetInfo &TI = Context.getTargetInfo(); TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); if (A == TargetInfo::CCCR_Warning) { @@ -4774,6 +4783,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, break; case AttributeList::AT_StdCall: case AttributeList::AT_CDecl: + case AttributeList::AT_ColdCC: case AttributeList::AT_FastCall: case AttributeList::AT_ThisCall: case AttributeList::AT_Pascal: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c47a7f59ac..402e522eeb 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -100,6 +100,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, #define FUNCTION_TYPE_ATTRS_CASELIST \ case AttributeList::AT_NoReturn: \ case AttributeList::AT_CDecl: \ + case AttributeList::AT_ColdCC: \ case AttributeList::AT_FastCall: \ case AttributeList::AT_StdCall: \ case AttributeList::AT_ThisCall: \ @@ -3103,6 +3104,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_NoReturn; case AttributedType::attr_cdecl: return AttributeList::AT_CDecl; + case AttributedType::attr_coldcc: + return AttributeList::AT_ColdCC; case AttributedType::attr_fastcall: return AttributeList::AT_FastCall; case AttributedType::attr_stdcall: diff --git a/test/CodeGen/coldcc.c b/test/CodeGen/coldcc.c new file mode 100644 index 0000000000..8965cadfe4 --- /dev/null +++ b/test/CodeGen/coldcc.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -Werror -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Werror -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple armv7-unknown-unknown -Werror -emit-llvm -o - %s | FileCheck %s + +void __attribute__((coldcc)) f1(void); + +void f2(void) { + f1(); +// CHECK: call coldcc void @f1() +} + +// CHECK: declare coldcc void @f1() diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 945eb11427..90175c7980 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -500,6 +500,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(AAPCS_VFP); TCALLINGCONV(PnaclCall); TCALLINGCONV(IntelOclBicc); + TCALLINGCONV(Cold); } #undef TCALLINGCONV }