Add frontend support for __vectorcall
authorReid Kleckner <reid@kleckner.net>
Fri, 24 Oct 2014 17:42:17 +0000 (17:42 +0000)
committerReid Kleckner <reid@kleckner.net>
Fri, 24 Oct 2014 17:42:17 +0000 (17:42 +0000)
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

26 files changed:
clang/include/clang-c/Index.h
clang/include/clang/AST/Type.h
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/Specifiers.h
clang/include/clang/Basic/TokenKinds.def
clang/lib/AST/Expr.cpp
clang/lib/AST/MicrosoftMangle.cpp
clang/lib/AST/Type.cpp
clang/lib/AST/TypePrinter.cpp
clang/lib/Basic/Targets.cpp
clang/lib/CodeGen/CGCall.cpp
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseTentative.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaType.cpp
clang/test/CodeGen/microsoft-call-conv.c
clang/test/CodeGen/mrtd.c
clang/test/CodeGenCXX/mangle-ms.cpp
clang/test/Sema/callingconv.c
clang/test/Sema/decl-microsoft-call-conv.c
clang/test/Sema/stdcall-fastcall.c
clang/test/SemaCXX/decl-microsoft-call-conv.cpp
clang/tools/libclang/CXType.cpp

index 3892949..6e3bd07 100644 (file)
@@ -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
index 1391586..bd84305 100644 (file)
@@ -3432,6 +3432,7 @@ public:
     attr_stdcall,
     attr_thiscall,
     attr_pascal,
+    attr_vectorcall,
     attr_pnaclcall,
     attr_inteloclbicc,
     attr_ms_abi,
index 96699f0..ed86c4f 100644 (file)
@@ -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];
index 42bc784..cf8b662 100644 (file)
@@ -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
index 8197f7d..bf9148e 100644 (file)
@@ -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">;
index f895673..a968d00 100644 (file)
@@ -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;
     }
   }
 
index 2ecc5f5..d2b06df 100644 (file)
@@ -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)
index fabcf0c..5020d5a 100644 (file)
@@ -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;
       }
index 59cf4d0..ca16db4 100644 (file)
@@ -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(
index 4bf5927..e9d474a 100644 (file)
@@ -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:
index 061473e..bbd53ed 100644 (file)
@@ -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;
index 957448a..4604b1c 100644 (file)
@@ -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;
   }
index 4c82e90..ab141d4 100644 (file)
@@ -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;
 
index eb77b09..054df9f 100644 (file)
@@ -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());
index 4060fab..8463138 100644 (file)
@@ -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:
index 1666551..f16ef0c 100644 (file)
@@ -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
index d252bdc..f6a89d7 100644 (file)
@@ -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:
index 4b4a7ef..a6f9483 100644 (file)
@@ -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;
index b80c58d..aabe825 100644 (file)
@@ -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;
 }
 
index 1132d04..f929d4c 100644 (file)
@@ -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);
 
index 3285c98..bf61d8b 100644 (file)
@@ -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"
index 6890815..5ac5a4a 100644 (file)
@@ -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) {
index fefa862..c8fb6e1 100644 (file)
@@ -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() {}
index e19b110..256f558 100644 (file)
@@ -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
index eb6c850..a4b68cd 100644 (file)
@@ -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) {}
index fe45899..81cff5a 100644 (file)
@@ -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);