forked from OSchip/llvm-project
Add frontend support for __vectorcall
Wire it through everywhere we have support for fastcall, essentially. This allows us to parse the MSVC "14" CTP headers, but we will miscompile them because LLVM doesn't support __vectorcall yet. Reviewed By: Aaron Ballman Differential Revision: http://reviews.llvm.org/D5808 llvm-svn: 220573
This commit is contained in:
parent
d024f528b4
commit
d7857f05f4
|
@ -2853,6 +2853,7 @@ enum CXCallingConv {
|
|||
CXCallingConv_IntelOclBicc = 9,
|
||||
CXCallingConv_X86_64Win64 = 10,
|
||||
CXCallingConv_X86_64SysV = 11,
|
||||
CXCallingConv_X86VectorCall = 12,
|
||||
|
||||
CXCallingConv_Invalid = 100,
|
||||
CXCallingConv_Unexposed = 200
|
||||
|
|
|
@ -3432,6 +3432,7 @@ public:
|
|||
attr_stdcall,
|
||||
attr_thiscall,
|
||||
attr_pascal,
|
||||
attr_vectorcall,
|
||||
attr_pnaclcall,
|
||||
attr_inteloclbicc,
|
||||
attr_ms_abi,
|
||||
|
|
|
@ -1167,6 +1167,13 @@ def ThisCall : InheritableAttr {
|
|||
let Documentation = [ThisCallDocs];
|
||||
}
|
||||
|
||||
def VectorCall : InheritableAttr {
|
||||
let Spellings = [GNU<"vectorcall">, Keyword<"__vectorcall">,
|
||||
Keyword<"_vectorcall">];
|
||||
// let Subjects = [Function, ObjCMethod];
|
||||
let Documentation = [VectorCallDocs];
|
||||
}
|
||||
|
||||
def Pascal : InheritableAttr {
|
||||
let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
|
||||
// let Subjects = [Function, ObjCMethod];
|
||||
|
|
|
@ -761,6 +761,32 @@ MSDN.
|
|||
}];
|
||||
}
|
||||
|
||||
def VectorCallDocs : Documentation {
|
||||
let Category = DocCatCallingConvs;
|
||||
let Content = [{
|
||||
On 32-bit x86 *and* x86_64 targets, this attribute changes the calling
|
||||
convention of a function to pass vector parameters in SSE registers.
|
||||
|
||||
On 32-bit x86 targets, this calling convention is similar to ``__fastcall``.
|
||||
The first two integer parameters are passed in ECX and EDX. Subsequent integer
|
||||
parameters are passed in memory, and callee clears the stack. On x86_64
|
||||
targets, the callee does *not* clear the stack, and integer parameters are
|
||||
passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling
|
||||
convention.
|
||||
|
||||
On both 32-bit x86 and x86_64 targets, vector and floating point arguments are
|
||||
passed in XMM0-XMM5. Homogenous vector aggregates of up to four elements are
|
||||
passed in sequential SSE registers if enough are available. If AVX is enabled,
|
||||
256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that
|
||||
cannot be passed in registers for any reason is passed by reference, which
|
||||
allows the caller to align the parameter memory.
|
||||
|
||||
See the documentation for `__vectorcall`_ on MSDN for more details.
|
||||
|
||||
.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx
|
||||
}];
|
||||
}
|
||||
|
||||
def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> {
|
||||
let Content = [{
|
||||
Clang supports additional attributes for checking basic resource management
|
||||
|
|
|
@ -2255,9 +2255,9 @@ def err_cconv_change : Error<
|
|||
def warn_cconv_ignored : Warning<
|
||||
"calling convention %0 ignored for this target">, InGroup<IgnoredAttributes>;
|
||||
def err_cconv_knr : Error<
|
||||
"function with no prototype cannot use the callee-cleanup %0 calling convention">;
|
||||
"function with no prototype cannot use the %0 calling convention">;
|
||||
def warn_cconv_knr : Warning<
|
||||
"function with no prototype cannot use the callee-cleanup %0 calling convention">,
|
||||
err_cconv_knr.Text>,
|
||||
InGroup<DiagGroup<"missing-prototype-for-cc">>;
|
||||
def err_cconv_varargs : Error<
|
||||
"variadic function cannot use %0 calling convention">;
|
||||
|
|
|
@ -203,6 +203,7 @@ namespace clang {
|
|||
CC_X86StdCall, // __attribute__((stdcall))
|
||||
CC_X86FastCall, // __attribute__((fastcall))
|
||||
CC_X86ThisCall, // __attribute__((thiscall))
|
||||
CC_X86VectorCall, // __attribute__((vectorcall))
|
||||
CC_X86Pascal, // __attribute__((pascal))
|
||||
CC_X86_64Win64, // __attribute__((ms_abi))
|
||||
CC_X86_64SysV, // __attribute__((sysv_abi))
|
||||
|
@ -212,16 +213,18 @@ namespace clang {
|
|||
CC_IntelOclBicc // __attribute__((intel_ocl_bicc))
|
||||
};
|
||||
|
||||
/// \brief Checks whether the given calling convention is callee-cleanup.
|
||||
inline bool isCalleeCleanup(CallingConv CC) {
|
||||
/// \brief Checks whether the given calling convention supports variadic
|
||||
/// calls. Unprototyped calls also use the variadic call rules.
|
||||
inline bool supportsVariadicCall(CallingConv CC) {
|
||||
switch (CC) {
|
||||
case CC_X86StdCall:
|
||||
case CC_X86FastCall:
|
||||
case CC_X86ThisCall:
|
||||
case CC_X86Pascal:
|
||||
return true;
|
||||
default:
|
||||
case CC_X86VectorCall:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -457,6 +457,7 @@ KEYWORD(__cdecl , KEYALL)
|
|||
KEYWORD(__stdcall , KEYALL)
|
||||
KEYWORD(__fastcall , KEYALL)
|
||||
KEYWORD(__thiscall , KEYALL)
|
||||
KEYWORD(__vectorcall , KEYALL)
|
||||
KEYWORD(__forceinline , KEYMS)
|
||||
KEYWORD(__unaligned , KEYMS)
|
||||
KEYWORD(__super , KEYMS)
|
||||
|
@ -560,6 +561,7 @@ ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND)
|
|||
ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND)
|
||||
ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND)
|
||||
ALIAS("_thiscall" , __thiscall , KEYMS)
|
||||
ALIAS("_vectorcall" , __vectorcall, KEYMS)
|
||||
ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
|
||||
ALIAS("_inline" , inline , KEYMS)
|
||||
ALIAS("_declspec" , __declspec , KEYMS)
|
||||
|
|
|
@ -546,6 +546,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
|
|||
case CC_X86StdCall: POut << "__stdcall "; break;
|
||||
case CC_X86FastCall: POut << "__fastcall "; break;
|
||||
case CC_X86ThisCall: POut << "__thiscall "; break;
|
||||
case CC_X86VectorCall: POut << "__vectorcall "; break;
|
||||
// Only bother printing the conventions that MSVC knows about.
|
||||
default: break;
|
||||
}
|
||||
|
|
|
@ -1687,6 +1687,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
|
|||
// ::= H # __export __stdcall
|
||||
// ::= I # __fastcall
|
||||
// ::= J # __export __fastcall
|
||||
// ::= Q # __vectorcall
|
||||
// The 'export' calling conventions are from a bygone era
|
||||
// (*cough*Win16*cough*) when functions were declared for export with
|
||||
// that keyword. (It didn't actually export them, it just made them so
|
||||
|
@ -1703,6 +1704,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
|
|||
case CC_X86ThisCall: Out << 'E'; break;
|
||||
case CC_X86StdCall: Out << 'G'; break;
|
||||
case CC_X86FastCall: Out << 'I'; break;
|
||||
case CC_X86VectorCall: Out << 'Q'; break;
|
||||
}
|
||||
}
|
||||
void MicrosoftCXXNameMangler::mangleThrowSpecification(
|
||||
|
|
|
@ -1578,6 +1578,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
|
|||
case CC_X86FastCall: return "fastcall";
|
||||
case CC_X86ThisCall: return "thiscall";
|
||||
case CC_X86Pascal: return "pascal";
|
||||
case CC_X86VectorCall: return "vectorcall";
|
||||
case CC_X86_64Win64: return "ms_abi";
|
||||
case CC_X86_64SysV: return "sysv_abi";
|
||||
case CC_AAPCS: return "aapcs";
|
||||
|
@ -1913,6 +1914,7 @@ bool AttributedType::isCallingConv() const {
|
|||
case attr_fastcall:
|
||||
case attr_stdcall:
|
||||
case attr_thiscall:
|
||||
case attr_vectorcall:
|
||||
case attr_pascal:
|
||||
case attr_ms_abi:
|
||||
case attr_sysv_abi:
|
||||
|
|
|
@ -673,6 +673,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
|
|||
case CC_X86ThisCall:
|
||||
OS << " __attribute__((thiscall))";
|
||||
break;
|
||||
case CC_X86VectorCall:
|
||||
OS << " __attribute__((vectorcall))";
|
||||
break;
|
||||
case CC_X86Pascal:
|
||||
OS << " __attribute__((pascal))";
|
||||
break;
|
||||
|
@ -1235,6 +1238,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
|
|||
case AttributedType::attr_fastcall: OS << "fastcall"; break;
|
||||
case AttributedType::attr_stdcall: OS << "stdcall"; break;
|
||||
case AttributedType::attr_thiscall: OS << "thiscall"; break;
|
||||
case AttributedType::attr_vectorcall: OS << "vectorcall"; break;
|
||||
case AttributedType::attr_pascal: OS << "pascal"; break;
|
||||
case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
|
||||
case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
|
||||
|
|
|
@ -2095,8 +2095,9 @@ 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_X86VectorCall ||
|
||||
CC == CC_C ||
|
||||
CC == CC_X86Pascal ||
|
||||
CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,10 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
|
|||
case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS;
|
||||
case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP;
|
||||
case CC_IntelOclBicc: return llvm::CallingConv::Intel_OCL_BI;
|
||||
// TODO: add support for CC_X86Pascal to llvm
|
||||
// TODO: Add support for __pascal to LLVM.
|
||||
case CC_X86Pascal: return llvm::CallingConv::C;
|
||||
// TODO: Add support for __vectorcall to LLVM.
|
||||
case CC_X86VectorCall: return llvm::CallingConv::C;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +121,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
|
|||
if (D->hasAttr<ThisCallAttr>())
|
||||
return CC_X86ThisCall;
|
||||
|
||||
if (D->hasAttr<VectorCallAttr>())
|
||||
return CC_X86VectorCall;
|
||||
|
||||
if (D->hasAttr<PascalAttr>())
|
||||
return CC_X86Pascal;
|
||||
|
||||
|
|
|
@ -588,15 +588,28 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) {
|
|||
|
||||
void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
|
||||
// Treat these like attributes
|
||||
while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
|
||||
Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) ||
|
||||
Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) ||
|
||||
Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned) ||
|
||||
Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) {
|
||||
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
|
||||
SourceLocation AttrNameLoc = ConsumeToken();
|
||||
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
|
||||
AttributeList::AS_Keyword);
|
||||
while (true) {
|
||||
switch (Tok.getKind()) {
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___stdcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___cdecl:
|
||||
case tok::kw___vectorcall:
|
||||
case tok::kw___ptr64:
|
||||
case tok::kw___w64:
|
||||
case tok::kw___ptr32:
|
||||
case tok::kw___unaligned:
|
||||
case tok::kw___sptr:
|
||||
case tok::kw___uptr: {
|
||||
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
|
||||
SourceLocation AttrNameLoc = ConsumeToken();
|
||||
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
|
||||
AttributeList::AS_Keyword);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2876,6 +2889,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
case tok::kw___stdcall:
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___vectorcall:
|
||||
case tok::kw___unaligned:
|
||||
ParseMicrosoftTypeAttributes(DS.getAttributes());
|
||||
continue;
|
||||
|
@ -4066,6 +4080,7 @@ bool Parser::isTypeSpecifierQualifier() {
|
|||
case tok::kw___stdcall:
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___vectorcall:
|
||||
case tok::kw___w64:
|
||||
case tok::kw___ptr64:
|
||||
case tok::kw___ptr32:
|
||||
|
@ -4234,6 +4249,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
|
|||
case tok::kw___stdcall:
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___vectorcall:
|
||||
case tok::kw___w64:
|
||||
case tok::kw___sptr:
|
||||
case tok::kw___uptr:
|
||||
|
@ -4457,6 +4473,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
|
|||
case tok::kw___stdcall:
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___vectorcall:
|
||||
case tok::kw___unaligned:
|
||||
if (AttrReqs & AR_DeclspecAttributesParsed) {
|
||||
ParseMicrosoftTypeAttributes(DS.getAttributes());
|
||||
|
|
|
@ -837,6 +837,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
|
|||
Tok.is(tok::kw___stdcall) ||
|
||||
Tok.is(tok::kw___fastcall) ||
|
||||
Tok.is(tok::kw___thiscall) ||
|
||||
Tok.is(tok::kw___vectorcall) ||
|
||||
Tok.is(tok::kw___unaligned))
|
||||
return TPResult::True; // attributes indicate declaration
|
||||
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
|
||||
|
@ -984,6 +985,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
|
|||
case tok::kw___stdcall:
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___vectorcall:
|
||||
case tok::kw___unaligned:
|
||||
case tok::kw___vector:
|
||||
case tok::kw___pixel:
|
||||
|
@ -1254,6 +1256,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
|
|||
case tok::kw___stdcall:
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___vectorcall:
|
||||
case tok::kw___w64:
|
||||
case tok::kw___sptr:
|
||||
case tok::kw___uptr:
|
||||
|
|
|
@ -7943,12 +7943,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
|||
|
||||
// Semantic checking for this function declaration (in isolation).
|
||||
|
||||
// Diagnose the use of callee-cleanup calls on unprototyped functions.
|
||||
// Diagnose calling conventions that don't support variadic calls.
|
||||
QualType NewQType = Context.getCanonicalType(NewFD->getType());
|
||||
const FunctionType *NewType = cast<FunctionType>(NewQType);
|
||||
if (isa<FunctionNoProtoType>(NewType)) {
|
||||
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
|
||||
if (isCalleeCleanup(NewTypeInfo.getCC())) {
|
||||
if (!supportsVariadicCall(NewTypeInfo.getCC())) {
|
||||
// Windows system headers sometimes accidentally use stdcall without
|
||||
// (void) parameters, so use a default-error warning in this case :-/
|
||||
int DiagID = NewTypeInfo.getCC() == CC_X86StdCall
|
||||
|
|
|
@ -3226,6 +3226,11 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
PascalAttr(Attr.getRange(), S.Context,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
return;
|
||||
case AttributeList::AT_VectorCall:
|
||||
D->addAttr(::new (S.Context)
|
||||
VectorCallAttr(Attr.getRange(), S.Context,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
return;
|
||||
case AttributeList::AT_MSABI:
|
||||
D->addAttr(::new (S.Context)
|
||||
MSABIAttr(Attr.getRange(), S.Context,
|
||||
|
@ -3288,6 +3293,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
|
|||
case AttributeList::AT_StdCall: CC = CC_X86StdCall; break;
|
||||
case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break;
|
||||
case AttributeList::AT_Pascal: CC = CC_X86Pascal; break;
|
||||
case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break;
|
||||
case AttributeList::AT_MSABI:
|
||||
CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
|
||||
CC_X86_64Win64;
|
||||
|
@ -4529,6 +4535,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
case AttributeList::AT_FastCall:
|
||||
case AttributeList::AT_ThisCall:
|
||||
case AttributeList::AT_Pascal:
|
||||
case AttributeList::AT_VectorCall:
|
||||
case AttributeList::AT_MSABI:
|
||||
case AttributeList::AT_SysVABI:
|
||||
case AttributeList::AT_Pcs:
|
||||
|
|
|
@ -107,6 +107,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
|
|||
case AttributeList::AT_StdCall: \
|
||||
case AttributeList::AT_ThisCall: \
|
||||
case AttributeList::AT_Pascal: \
|
||||
case AttributeList::AT_VectorCall: \
|
||||
case AttributeList::AT_MSABI: \
|
||||
case AttributeList::AT_SysVABI: \
|
||||
case AttributeList::AT_Regparm: \
|
||||
|
@ -3418,6 +3419,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
|
|||
return AttributeList::AT_ThisCall;
|
||||
case AttributedType::attr_pascal:
|
||||
return AttributeList::AT_Pascal;
|
||||
case AttributedType::attr_vectorcall:
|
||||
return AttributeList::AT_VectorCall;
|
||||
case AttributedType::attr_pcs:
|
||||
case AttributedType::attr_pcs_vfp:
|
||||
return AttributeList::AT_Pcs;
|
||||
|
@ -4434,6 +4437,8 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
|
|||
return AttributedType::attr_thiscall;
|
||||
case AttributeList::AT_Pascal:
|
||||
return AttributedType::attr_pascal;
|
||||
case AttributeList::AT_VectorCall:
|
||||
return AttributedType::attr_vectorcall;
|
||||
case AttributeList::AT_Pcs: {
|
||||
// The attribute may have had a fixit applied where we treated an
|
||||
// identifier as a string literal. The contents of the string are valid,
|
||||
|
@ -4551,7 +4556,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
|
|||
}
|
||||
|
||||
// Diagnose use of callee-cleanup calling convention on variadic functions.
|
||||
if (isCalleeCleanup(CC)) {
|
||||
if (!supportsVariadicCall(CC)) {
|
||||
const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn);
|
||||
if (FnP && FnP->isVariadic()) {
|
||||
unsigned DiagID = diag::err_cconv_varargs;
|
||||
|
|
|
@ -20,6 +20,12 @@ void __thiscall f6(void) {
|
|||
f3();
|
||||
// CHECK: call x86_thiscallcc void @f3()
|
||||
}
|
||||
// FIXME: Add this to LLVM.
|
||||
void __vectorcall f61(void) {
|
||||
// CHECK-LABEL: define void @f61()
|
||||
f3();
|
||||
// CHECK: call x86_thiscallcc void @f3()
|
||||
}
|
||||
|
||||
// PR5280
|
||||
void (__fastcall *pf1)(void) = f1;
|
||||
|
@ -28,19 +34,22 @@ void (__thiscall *pf3)(void) = f3;
|
|||
void (__fastcall *pf4)(void) = f4;
|
||||
void (__stdcall *pf5)(void) = f5;
|
||||
void (__thiscall *pf6)(void) = f6;
|
||||
void (__vectorcall *pf7)(void) = f61;
|
||||
|
||||
int main(void) {
|
||||
f4(); f5(); f6();
|
||||
f4(); f5(); f6(); f61();
|
||||
// CHECK: call x86_fastcallcc void @f4()
|
||||
// CHECK: call x86_stdcallcc void @f5()
|
||||
// CHECK: call x86_thiscallcc void @f6()
|
||||
pf1(); pf2(); pf3(); pf4(); pf5(); pf6();
|
||||
// CHECK: call void @f61()
|
||||
pf1(); pf2(); pf3(); pf4(); pf5(); pf6(); pf7();
|
||||
// CHECK: call x86_fastcallcc void %{{.*}}()
|
||||
// CHECK: call x86_stdcallcc void %{{.*}}()
|
||||
// CHECK: call x86_thiscallcc void %{{.*}}()
|
||||
// CHECK: call x86_fastcallcc void %{{.*}}()
|
||||
// CHECK: call x86_stdcallcc void %{{.*}}()
|
||||
// CHECK: call x86_thiscallcc void %{{.*}}()
|
||||
// CHECK: call void %{{.*}}()
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// 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 callee-cleanup stdcall calling convention
|
||||
// CHECK: mrtd.c:10:3: warning: function with no prototype cannot use the stdcall calling convention
|
||||
|
||||
void baz(int arg);
|
||||
|
||||
|
|
|
@ -365,3 +365,5 @@ void TypedefNewDelete::operator delete[](void *) { }
|
|||
// CHECK-DAG: ??3TypedefNewDelete@@SAXPAX@Z
|
||||
// CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z
|
||||
|
||||
void __vectorcall vector_func() { }
|
||||
// CHECK-DAG: @"\01?vector_func@@YQXXZ"
|
||||
|
|
|
@ -10,7 +10,7 @@ void __attribute__((stdcall)) bar(float *a) {
|
|||
void __attribute__((fastcall(1))) baz(float *a) { // expected-error {{'fastcall' attribute takes no arguments}}
|
||||
}
|
||||
|
||||
void __attribute__((fastcall)) test0() { // expected-error {{function with no prototype cannot use the callee-cleanup fastcall calling convention}}
|
||||
void __attribute__((fastcall)) test0() { // expected-error {{function with no prototype cannot use the fastcall calling convention}}
|
||||
}
|
||||
|
||||
void __attribute__((fastcall)) test1(void) {
|
||||
|
|
|
@ -11,11 +11,14 @@ void __thiscall CrcGenerateTableThiscall(void);
|
|||
void __thiscall CrcGenerateTableThiscall() {}
|
||||
void __pascal CrcGenerateTablePascal(void);
|
||||
void __pascal CrcGenerateTablePascal() {}
|
||||
void __vectorcall CrcGenerateTableVectorcall(void);
|
||||
void __vectorcall CrcGenerateTableVectorcall() {}
|
||||
|
||||
void __fastcall CrcGenerateTableNoProtoFastcall() {} // expected-error{{function with no prototype cannot use the callee-cleanup fastcall calling convention}}
|
||||
void __stdcall CrcGenerateTableNoProtoStdcall() {} // expected-warning{{function with no prototype cannot use the callee-cleanup stdcall calling convention}}
|
||||
void __thiscall CrcGenerateTableNoProtoThiscall() {} // expected-error{{function with no prototype cannot use the callee-cleanup thiscall calling convention}}
|
||||
void __pascal CrcGenerateTableNoProtoPascal() {} // expected-error{{function with no prototype cannot use the callee-cleanup pascal calling convention}}
|
||||
void __fastcall CrcGenerateTableNoProtoFastcall() {} // expected-error{{function with no prototype cannot use the fastcall calling convention}}
|
||||
void __stdcall CrcGenerateTableNoProtoStdcall() {} // expected-warning{{function with no prototype cannot use the stdcall calling convention}}
|
||||
void __thiscall CrcGenerateTableNoProtoThiscall() {} // expected-error{{function with no prototype cannot use the thiscall calling convention}}
|
||||
void __pascal CrcGenerateTableNoProtoPascal() {} // expected-error{{function with no prototype cannot use the pascal calling convention}}
|
||||
void __vectorcall CrcGenerateTableNoProtoVectorcall() {} // expected-error{{function with no prototype cannot use the vectorcall calling convention}}
|
||||
|
||||
// Regular calling convention is fine.
|
||||
void CrcGenerateTableNoProto() {}
|
||||
|
|
|
@ -6,7 +6,7 @@ int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies
|
|||
|
||||
// Different CC qualifiers are not compatible
|
||||
void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{fastcall and stdcall attributes are not compatible}}
|
||||
void __attribute__((stdcall)) foo4(); // expected-note{{previous declaration is here}} expected-warning{{function with no prototype cannot use the callee-cleanup stdcall calling convention}}
|
||||
void __attribute__((stdcall)) foo4(); // expected-note{{previous declaration is here}} expected-warning{{function with no prototype cannot use the stdcall calling convention}}
|
||||
void __attribute__((fastcall)) foo4(void); // expected-error{{function declared 'fastcall' here was previously declared 'stdcall'}}
|
||||
|
||||
// rdar://8876096
|
||||
|
|
|
@ -10,6 +10,7 @@ void free_func_default(); // expected-note 2 {{previous declaration i
|
|||
void __cdecl free_func_cdecl(); // expected-note 2 {{previous declaration is here}}
|
||||
void __stdcall free_func_stdcall(); // expected-note 2 {{previous declaration is here}}
|
||||
void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}}
|
||||
void __vectorcall free_func_vectorcall(); // expected-note 2 {{previous declaration is here}}
|
||||
|
||||
void __cdecl free_func_default();
|
||||
void __stdcall free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
|
||||
|
@ -27,6 +28,10 @@ void __cdecl free_func_fastcall(); // expected-error {{function declared 'cde
|
|||
void __stdcall free_func_fastcall(); // expected-error {{function declared 'stdcall' here was previously declared 'fastcall'}}
|
||||
void free_func_fastcall();
|
||||
|
||||
void __cdecl free_func_vectorcall(); // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}
|
||||
void __stdcall free_func_vectorcall(); // expected-error {{function declared 'stdcall' here was previously declared 'vectorcall'}}
|
||||
void free_func_vectorcall();
|
||||
|
||||
// Overloaded functions may have different calling conventions
|
||||
void __fastcall free_func_default(int);
|
||||
void __cdecl free_func_default(int *);
|
||||
|
@ -45,6 +50,8 @@ struct S {
|
|||
void __cdecl member_cdecl2(); // expected-note {{previous declaration is here}}
|
||||
void __thiscall member_thiscall1();
|
||||
void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}}
|
||||
void __vectorcall member_vectorcall1();
|
||||
void __vectorcall member_vectorcall2(); // expected-note {{previous declaration is here}}
|
||||
|
||||
// Typedefs carrying the __cdecl convention are adjusted to __thiscall.
|
||||
void_fun_t member_typedef_default; // expected-note {{previous declaration is here}}
|
||||
|
@ -83,6 +90,9 @@ void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thi
|
|||
void S::member_thiscall1() {}
|
||||
void __cdecl S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}}
|
||||
|
||||
void S::member_vectorcall1() {}
|
||||
void __cdecl S::member_vectorcall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}
|
||||
|
||||
void S::static_member_default1() {}
|
||||
void __cdecl S::static_member_default2() {}
|
||||
void __stdcall S::static_member_default3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
|
||||
|
@ -143,9 +153,10 @@ void __attribute__((noreturn)) __stdcall __attribute__((regparm(1))) multi_attri
|
|||
void multi_attribute(int x) { __builtin_unreachable(); }
|
||||
|
||||
|
||||
// expected-error@+3 {{vectorcall and cdecl attributes are not compatible}}
|
||||
// expected-error@+2 {{stdcall and cdecl attributes are not compatible}}
|
||||
// expected-error@+1 {{fastcall and cdecl attributes are not compatible}}
|
||||
void __cdecl __cdecl __stdcall __cdecl __fastcall multi_cc(int x);
|
||||
void __cdecl __cdecl __stdcall __cdecl __fastcall __vectorcall multi_cc(int x);
|
||||
|
||||
template <typename T> void __stdcall StdcallTemplate(T) {}
|
||||
template <> void StdcallTemplate<int>(int) {}
|
||||
|
|
|
@ -520,6 +520,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
|
|||
TCALLINGCONV(X86FastCall);
|
||||
TCALLINGCONV(X86ThisCall);
|
||||
TCALLINGCONV(X86Pascal);
|
||||
TCALLINGCONV(X86VectorCall);
|
||||
TCALLINGCONV(X86_64Win64);
|
||||
TCALLINGCONV(X86_64SysV);
|
||||
TCALLINGCONV(AAPCS);
|
||||
|
|
Loading…
Reference in New Issue