зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
0b849d34b3
Коммит
4c67aa9640
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче