Add support for coldcc to clang

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175912 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Collingbourne 2013-02-22 19:24:35 +00:00
Родитель 0b849d34b3
Коммит 4c67aa9640
15 изменённых файлов: 59 добавлений и 12 удалений

Просмотреть файл

@ -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 In this case Clang does not warn because the format string ``s`` and
the corresponding arguments are annotated. If the arguments are the corresponding arguments are annotated. If the arguments are
incorrect, the caller of ``foo`` will receive a warning. incorrect, the caller of ``foo`` will receive a warning.
LLVM-Specific Calling Conventions
=================================
Clang supports `LLVM's coldcc calling convention
<http://llvm.org/docs/LangRef.html#calling-conventions>`_ 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.

Просмотреть файл

@ -2674,6 +2674,7 @@ enum CXCallingConv {
CXCallingConv_AAPCS_VFP = 7, CXCallingConv_AAPCS_VFP = 7,
CXCallingConv_PnaclCall = 8, CXCallingConv_PnaclCall = 8,
CXCallingConv_IntelOclBicc = 9, CXCallingConv_IntelOclBicc = 9,
CXCallingConv_Cold = 10,
CXCallingConv_Invalid = 100, CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200 CXCallingConv_Unexposed = 200

Просмотреть файл

@ -3323,6 +3323,7 @@ public:
// No operand. // No operand.
attr_noreturn, attr_noreturn,
attr_cdecl, attr_cdecl,
attr_coldcc,
attr_fastcall, attr_fastcall,
attr_stdcall, attr_stdcall,
attr_thiscall, attr_thiscall,

Просмотреть файл

@ -277,6 +277,10 @@ def Cold : InheritableAttr {
let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">]; let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">];
} }
def ColdCC : InheritableAttr {
let Spellings = [GNU<"coldcc">, CXX11<"clang", "coldcc">];
}
def Common : InheritableAttr { def Common : InheritableAttr {
let Spellings = [GNU<"common">, CXX11<"gnu", "common">]; let Spellings = [GNU<"common">, CXX11<"gnu", "common">];
} }

Просмотреть файл

@ -188,6 +188,7 @@ namespace clang {
enum CallingConv { enum CallingConv {
CC_Default, CC_Default,
CC_C, // __attribute__((cdecl)) CC_C, // __attribute__((cdecl))
CC_Cold, // __attribute__((coldcc))
CC_X86StdCall, // __attribute__((stdcall)) CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall)) CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall, // __attribute__((thiscall)) CC_X86ThisCall, // __attribute__((thiscall))
@ -198,6 +199,10 @@ namespace clang {
CC_IntelOclBicc // __attribute__((intel_ocl_bicc)) CC_IntelOclBicc // __attribute__((intel_ocl_bicc))
}; };
inline bool isTargetSpecific(CallingConv CC) {
return CC >= CC_X86StdCall;
}
} // end namespace clang } // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H #endif // LLVM_CLANG_BASIC_SPECIFIERS_H

Просмотреть файл

@ -754,13 +754,7 @@ public:
/// and be substituted with the default calling convention, or (someday) /// and be substituted with the default calling convention, or (someday)
/// produce an error (such as using thiscall on a non-instance function). /// produce an error (such as using thiscall on a non-instance function).
virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
switch (CC) { return CCCR_Warning;
default:
return CCCR_Warning;
case CC_C:
case CC_Default:
return CCCR_OK;
}
} }
protected: protected:

Просмотреть файл

@ -925,6 +925,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
case CC_PnaclCall: return set("cc", "pnaclcall"); case CC_PnaclCall: return set("cc", "pnaclcall");
case CC_IntelOclBicc: return set("cc", "intel_ocl_bicc"); case CC_IntelOclBicc: return set("cc", "intel_ocl_bicc");
case CC_Cold: return set("cc", "coldcc");
} }
} }

Просмотреть файл

@ -1547,6 +1547,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
llvm_unreachable("no name for default cc"); llvm_unreachable("no name for default cc");
case CC_C: return "cdecl"; case CC_C: return "cdecl";
case CC_Cold: return "coldcc";
case CC_X86StdCall: return "stdcall"; case CC_X86StdCall: return "stdcall";
case CC_X86FastCall: return "fastcall"; case CC_X86FastCall: return "fastcall";
case CC_X86ThisCall: return "thiscall"; case CC_X86ThisCall: return "thiscall";

Просмотреть файл

@ -626,6 +626,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_C: case CC_C:
OS << " __attribute__((cdecl))"; OS << " __attribute__((cdecl))";
break; break;
case CC_Cold:
OS << " __attribute__((coldcc))";
break;
case CC_X86StdCall: case CC_X86StdCall:
OS << " __attribute__((stdcall))"; OS << " __attribute__((stdcall))";
break; break;
@ -1156,6 +1159,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case AttributedType::attr_noreturn: OS << "noreturn"; break; case AttributedType::attr_noreturn: OS << "noreturn"; break;
case AttributedType::attr_cdecl: OS << "cdecl"; 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_fastcall: OS << "fastcall"; break;
case AttributedType::attr_stdcall: OS << "stdcall"; break; case AttributedType::attr_stdcall: OS << "stdcall"; break;
case AttributedType::attr_thiscall: OS << "thiscall"; break; case AttributedType::attr_thiscall: OS << "thiscall"; break;

Просмотреть файл

@ -1933,8 +1933,7 @@ public:
// We accept all non-ARM calling conventions // We accept all non-ARM calling conventions
return (CC == CC_X86ThisCall || return (CC == CC_X86ThisCall ||
CC == CC_X86FastCall || CC == CC_X86FastCall ||
CC == CC_X86StdCall || CC == CC_X86StdCall ||
CC == CC_C ||
CC == CC_X86Pascal || CC == CC_X86Pascal ||
CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning; CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning;
} }
@ -3027,9 +3026,7 @@ public:
} }
virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
return (CC == CC_Default || return CC == CC_IntelOclBicc ? CCCR_OK : CCCR_Warning;
CC == CC_C ||
CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning;
} }
virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const {

Просмотреть файл

@ -37,6 +37,7 @@ using namespace CodeGen;
static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
switch (CC) { switch (CC) {
default: return llvm::CallingConv::C; default: return llvm::CallingConv::C;
case CC_Cold: return llvm::CallingConv::Cold;
case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
@ -135,6 +136,9 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) {
static CallingConv getCallingConventionForDecl(const Decl *D) { static CallingConv getCallingConventionForDecl(const Decl *D) {
// Set the appropriate calling convention for the Function. // Set the appropriate calling convention for the Function.
if (D->hasAttr<ColdCCAttr>())
return CC_Cold;
if (D->hasAttr<StdCallAttr>()) if (D->hasAttr<StdCallAttr>())
return CC_X86StdCall; return CC_X86StdCall;

Просмотреть файл

@ -3859,6 +3859,11 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
} }
switch (Attr.getKind()) { switch (Attr.getKind()) {
case AttributeList::AT_ColdCC:
D->addAttr(::new (S.Context)
ColdCCAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
return;
case AttributeList::AT_FastCall: case AttributeList::AT_FastCall:
D->addAttr(::new (S.Context) D->addAttr(::new (S.Context)
FastCallAttr(Attr.getRange(), S.Context, FastCallAttr(Attr.getRange(), S.Context,
@ -3939,6 +3944,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
// move to TargetAttributesSema one day. // move to TargetAttributesSema one day.
switch (attr.getKind()) { switch (attr.getKind()) {
case AttributeList::AT_CDecl: CC = CC_C; break; 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_FastCall: CC = CC_X86FastCall; break;
case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; case AttributeList::AT_StdCall: CC = CC_X86StdCall; break;
case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; 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"); default: llvm_unreachable("unexpected attribute kind");
} }
if (!isTargetSpecific(CC))
return false;
const TargetInfo &TI = Context.getTargetInfo(); const TargetInfo &TI = Context.getTargetInfo();
TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
if (A == TargetInfo::CCCR_Warning) { if (A == TargetInfo::CCCR_Warning) {
@ -4774,6 +4783,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
break; break;
case AttributeList::AT_StdCall: case AttributeList::AT_StdCall:
case AttributeList::AT_CDecl: case AttributeList::AT_CDecl:
case AttributeList::AT_ColdCC:
case AttributeList::AT_FastCall: case AttributeList::AT_FastCall:
case AttributeList::AT_ThisCall: case AttributeList::AT_ThisCall:
case AttributeList::AT_Pascal: case AttributeList::AT_Pascal:

Просмотреть файл

@ -100,6 +100,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
#define FUNCTION_TYPE_ATTRS_CASELIST \ #define FUNCTION_TYPE_ATTRS_CASELIST \
case AttributeList::AT_NoReturn: \ case AttributeList::AT_NoReturn: \
case AttributeList::AT_CDecl: \ case AttributeList::AT_CDecl: \
case AttributeList::AT_ColdCC: \
case AttributeList::AT_FastCall: \ case AttributeList::AT_FastCall: \
case AttributeList::AT_StdCall: \ case AttributeList::AT_StdCall: \
case AttributeList::AT_ThisCall: \ case AttributeList::AT_ThisCall: \
@ -3103,6 +3104,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_NoReturn; return AttributeList::AT_NoReturn;
case AttributedType::attr_cdecl: case AttributedType::attr_cdecl:
return AttributeList::AT_CDecl; return AttributeList::AT_CDecl;
case AttributedType::attr_coldcc:
return AttributeList::AT_ColdCC;
case AttributedType::attr_fastcall: case AttributedType::attr_fastcall:
return AttributeList::AT_FastCall; return AttributeList::AT_FastCall;
case AttributedType::attr_stdcall: case AttributedType::attr_stdcall:

12
test/CodeGen/coldcc.c Normal file
Просмотреть файл

@ -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()

Просмотреть файл

@ -500,6 +500,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
TCALLINGCONV(AAPCS_VFP); TCALLINGCONV(AAPCS_VFP);
TCALLINGCONV(PnaclCall); TCALLINGCONV(PnaclCall);
TCALLINGCONV(IntelOclBicc); TCALLINGCONV(IntelOclBicc);
TCALLINGCONV(Cold);
} }
#undef TCALLINGCONV #undef TCALLINGCONV
} }