[PATCH] Add frontend support for __vectorcall

Aaron Ballman aaron at aaronballman.com
Thu Oct 16 05:35:02 PDT 2014


On Wed, Oct 15, 2014 at 6:36 PM, Reid Kleckner <rnk at google.com> wrote:
> Hi rsmith, majnemer,
>
> 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.
>
> http://reviews.llvm.org/D5808
>
> Files:
>   include/clang-c/Index.h
>   include/clang/AST/Type.h
>   include/clang/Basic/Attr.td
>   include/clang/Basic/DiagnosticSemaKinds.td
>   include/clang/Basic/Specifiers.h
>   include/clang/Basic/TokenKinds.def
>   lib/AST/Expr.cpp
>   lib/AST/MicrosoftMangle.cpp
>   lib/AST/Type.cpp
>   lib/AST/TypePrinter.cpp
>   lib/Basic/Targets.cpp
>   lib/CodeGen/CGCall.cpp
>   lib/Parse/ParseDecl.cpp
>   lib/Parse/ParseTentative.cpp
>   lib/Sema/SemaDecl.cpp
>   lib/Sema/SemaDeclAttr.cpp
>   lib/Sema/SemaType.cpp
>   test/CodeGen/microsoft-call-conv.c
>   test/CodeGen/mrtd.c
>   test/CodeGenCXX/mangle-ms.cpp
>   test/Sema/callingconv.c
>   test/Sema/decl-microsoft-call-conv.c
>   test/Sema/stdcall-fastcall.c
>   test/SemaCXX/decl-microsoft-call-conv.cpp
>   tools/libclang/CXType.cpp

Yay, new calling conventions for....x64.... ;-( Thank you for working on this!


> Index: include/clang-c/Index.h
> ===================================================================
> --- include/clang-c/Index.h
> +++ include/clang-c/Index.h
> @@ -2853,6 +2853,7 @@
>    CXCallingConv_IntelOclBicc = 9,
>    CXCallingConv_X86_64Win64 = 10,
>    CXCallingConv_X86_64SysV = 11,
> +  CXCallingConv_X86VectorCall = 12,

Isn't this an x86_64 attribute?

>
>    CXCallingConv_Invalid = 100,
>    CXCallingConv_Unexposed = 200
> Index: include/clang/AST/Type.h
> ===================================================================
> --- include/clang/AST/Type.h
> +++ include/clang/AST/Type.h
> @@ -3432,6 +3432,7 @@
>      attr_stdcall,
>      attr_thiscall,
>      attr_pascal,
> +    attr_vectorcall,
>      attr_pnaclcall,
>      attr_inteloclbicc,
>      attr_ms_abi,
> Index: include/clang/Basic/Attr.td
> ===================================================================
> --- include/clang/Basic/Attr.td
> +++ include/clang/Basic/Attr.td
> @@ -1167,6 +1167,13 @@
>    let Documentation = [Undocumented];
>  }
>
> +def VectorCall : InheritableAttr {
> +  let Spellings = [GCC<"vectorcall">, Keyword<"__vectorcall">,
> +                   Keyword<"_vectorcall">];

I can find no documentation that suggests GCC supports vectorcall. Are
we sure we want those spellings?

> +//  let Subjects = [Function, ObjCMethod];
> +  let Documentation = [Undocumented];

Please, no new undocumented attributes. (I know this is the first
calling convention one which will be documented; natch.)

> +}
> +
>  def Pascal : InheritableAttr {
>    let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
>  //  let Subjects = [Function, ObjCMethod];
> Index: include/clang/Basic/DiagnosticSemaKinds.td
> ===================================================================
> --- include/clang/Basic/DiagnosticSemaKinds.td
> +++ include/clang/Basic/DiagnosticSemaKinds.td
> @@ -2255,9 +2255,9 @@
>  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">,
> +  "function with no prototype cannot use the %0 calling convention">,

Could this be defined using err_cconv_knr.Text please?

>    InGroup<DiagGroup<"missing-prototype-for-cc">>;
>  def err_cconv_varargs : Error<
>    "variadic function cannot use %0 calling convention">;
> Index: include/clang/Basic/Specifiers.h
> ===================================================================
> --- include/clang/Basic/Specifiers.h
> +++ include/clang/Basic/Specifiers.h
> @@ -203,6 +203,7 @@
>      CC_X86StdCall,  // __attribute__((stdcall))
>      CC_X86FastCall, // __attribute__((fastcall))
>      CC_X86ThisCall, // __attribute__((thiscall))
> +    CC_X86VectorCall, // __attribute__((vectorcall))

Same comment about x86_64 here as elsewhere.

>      CC_X86Pascal,   // __attribute__((pascal))
>      CC_X86_64Win64, // __attribute__((ms_abi))
>      CC_X86_64SysV,  // __attribute__((sysv_abi))
> @@ -212,16 +213,18 @@
>      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) {

Can we make this function const while we're at it?

>      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: include/clang/Basic/TokenKinds.def
> ===================================================================
> --- include/clang/Basic/TokenKinds.def
> +++ include/clang/Basic/TokenKinds.def
> @@ -457,6 +457,7 @@
>  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("_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: lib/AST/Expr.cpp
> ===================================================================
> --- lib/AST/Expr.cpp
> +++ lib/AST/Expr.cpp
> @@ -557,6 +557,7 @@
>        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: lib/AST/MicrosoftMangle.cpp
> ===================================================================
> --- lib/AST/MicrosoftMangle.cpp
> +++ lib/AST/MicrosoftMangle.cpp
> @@ -1687,6 +1687,7 @@
>    //                      ::= 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 @@
>      case CC_X86ThisCall: Out << 'E'; break;
>      case CC_X86StdCall: Out << 'G'; break;
>      case CC_X86FastCall: Out << 'I'; break;
> +    case CC_X86VectorCall: Out << 'Q'; break;

Doesn't this also mangle in C, using @@? Or does that magic happen elsewhere?

>    }
>  }
>  void MicrosoftCXXNameMangler::mangleThrowSpecification(
> Index: lib/AST/Type.cpp
> ===================================================================
> --- lib/AST/Type.cpp
> +++ lib/AST/Type.cpp
> @@ -1577,6 +1577,7 @@
>    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";
> @@ -1912,6 +1913,7 @@
>    case attr_fastcall:
>    case attr_stdcall:
>    case attr_thiscall:
> +  case attr_vectorcall:
>    case attr_pascal:
>    case attr_ms_abi:
>    case attr_sysv_abi:
> Index: lib/AST/TypePrinter.cpp
> ===================================================================
> --- lib/AST/TypePrinter.cpp
> +++ lib/AST/TypePrinter.cpp
> @@ -673,6 +673,9 @@
>      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 @@
>    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: lib/Basic/Targets.cpp
> ===================================================================
> --- lib/Basic/Targets.cpp
> +++ lib/Basic/Targets.cpp
> @@ -2088,8 +2088,9 @@
>      // 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: lib/CodeGen/CGCall.cpp
> ===================================================================
> --- lib/CodeGen/CGCall.cpp
> +++ lib/CodeGen/CGCall.cpp
> @@ -48,6 +48,8 @@
>    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 __vectorcall to LLVM.
> +  case CC_X86VectorCall: return llvm::CallingConv::C;
>    }
>  }
>
> @@ -118,6 +120,9 @@
>    if (D->hasAttr<ThisCallAttr>())
>      return CC_X86ThisCall;
>
> +  if (D->hasAttr<VectorCallAttr>())
> +    return CC_X86VectorCall;
> +
>    if (D->hasAttr<PascalAttr>())
>      return CC_X86Pascal;
>
> Index: lib/Parse/ParseDecl.cpp
> ===================================================================
> --- lib/Parse/ParseDecl.cpp
> +++ lib/Parse/ParseDecl.cpp
> @@ -588,15 +588,28 @@
>
>  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;
> +    }
>    }
>  }
>
> @@ -2877,6 +2890,7 @@
>      case tok::kw___stdcall:
>      case tok::kw___fastcall:
>      case tok::kw___thiscall:
> +    case tok::kw___vectorcall:
>      case tok::kw___unaligned:
>        ParseMicrosoftTypeAttributes(DS.getAttributes());
>        continue;
> @@ -4067,6 +4081,7 @@
>    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:
> @@ -4235,6 +4250,7 @@
>    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:
> @@ -4458,6 +4474,7 @@
>      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: lib/Parse/ParseTentative.cpp
> ===================================================================
> --- lib/Parse/ParseTentative.cpp
> +++ lib/Parse/ParseTentative.cpp
> @@ -837,6 +837,7 @@
>            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 @@
>    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 @@
>    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: lib/Sema/SemaDecl.cpp
> ===================================================================
> --- lib/Sema/SemaDecl.cpp
> +++ lib/Sema/SemaDecl.cpp
> @@ -7941,12 +7941,12 @@
>
>    // 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: lib/Sema/SemaDeclAttr.cpp
> ===================================================================
> --- lib/Sema/SemaDeclAttr.cpp
> +++ lib/Sema/SemaDeclAttr.cpp
> @@ -3226,6 +3226,11 @@
>                 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 @@
>    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 @@
>    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: lib/Sema/SemaType.cpp
> ===================================================================
> --- lib/Sema/SemaType.cpp
> +++ lib/Sema/SemaType.cpp
> @@ -107,6 +107,7 @@
>      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 @@
>      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 @@
>      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 @@
>    }
>
>    // 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: test/CodeGen/microsoft-call-conv.c
> ===================================================================
> --- test/CodeGen/microsoft-call-conv.c
> +++ test/CodeGen/microsoft-call-conv.c
> @@ -20,27 +20,36 @@
>    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;
>  void (__stdcall *pf2)(void) = f2;
>  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: test/CodeGen/mrtd.c
> ===================================================================
> --- test/CodeGen/mrtd.c
> +++ test/CodeGen/mrtd.c
> @@ -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: test/CodeGenCXX/mangle-ms.cpp
> ===================================================================
> --- test/CodeGenCXX/mangle-ms.cpp
> +++ test/CodeGenCXX/mangle-ms.cpp
> @@ -365,3 +365,5 @@
>  // CHECK-DAG: ??3TypedefNewDelete@@SAXPAX at Z
>  // CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX at Z
>
> +void __vectorcall vector_func() { }
> +// CHECK-DAG: @"\01?vector_func@@YQXXZ"
> Index: test/Sema/callingconv.c
> ===================================================================
> --- test/Sema/callingconv.c
> +++ test/Sema/callingconv.c
> @@ -10,7 +10,7 @@
>  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: test/Sema/decl-microsoft-call-conv.c
> ===================================================================
> --- test/Sema/decl-microsoft-call-conv.c
> +++ test/Sema/decl-microsoft-call-conv.c
> @@ -11,11 +11,14 @@
>  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: test/Sema/stdcall-fastcall.c
> ===================================================================
> --- test/Sema/stdcall-fastcall.c
> +++ test/Sema/stdcall-fastcall.c
> @@ -6,7 +6,7 @@
>
>  // 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: test/SemaCXX/decl-microsoft-call-conv.cpp
> ===================================================================
> --- test/SemaCXX/decl-microsoft-call-conv.cpp
> +++ test/SemaCXX/decl-microsoft-call-conv.cpp
> @@ -10,6 +10,7 @@
>  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 __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 @@
>    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            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 multi_attribute(int x) { __builtin_unreachable(); }
>
>
> +// expected-error at +3 {{vectorcall and cdecl attributes are not compatible}}
>  // expected-error at +2 {{stdcall and cdecl attributes are not compatible}}
>  // expected-error at +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: tools/libclang/CXType.cpp
> ===================================================================
> --- tools/libclang/CXType.cpp
> +++ tools/libclang/CXType.cpp
> @@ -520,6 +520,7 @@
>        TCALLINGCONV(X86FastCall);
>        TCALLINGCONV(X86ThisCall);
>        TCALLINGCONV(X86Pascal);
> +      TCALLINGCONV(X86VectorCall);
>        TCALLINGCONV(X86_64Win64);
>        TCALLINGCONV(X86_64SysV);
>        TCALLINGCONV(AAPCS);
>

~Aaron



More information about the cfe-commits mailing list