From: Charles Davis Date: Fri, 30 Aug 2013 04:39:01 +0000 (+0000) Subject: Add ms_abi and sysv_abi attribute handling. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e8519c31a6ef853b627d557702ac1890f18ce2c9;p=clang Add ms_abi and sysv_abi attribute handling. Based on a patch by Benno Rice! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189644 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index d43c2d619a..b294e41439 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2694,6 +2694,8 @@ enum CXCallingConv { CXCallingConv_AAPCS_VFP = 7, CXCallingConv_PnaclCall = 8, CXCallingConv_IntelOclBicc = 9, + CXCallingConv_X86_64Win64 = 10, + CXCallingConv_X86_64SysV = 11, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 436fceeb80..ca2e42b8f3 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -3393,6 +3393,8 @@ public: attr_pascal, attr_pnaclcall, attr_inteloclbicc, + attr_ms_abi, + attr_sysv_abi, attr_ptr32, attr_ptr64, attr_sptr, diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index bd9e48f0e7..d38ffa60e1 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -426,6 +426,10 @@ def MayAlias : InheritableAttr { let Spellings = [GNU<"may_alias">, CXX11<"gnu", "may_alias">]; } +def MSABI : InheritableAttr { + let Spellings = [GNU<"ms_abi">, CXX11<"gnu", "ms_abi">]; +} + def MSP430Interrupt : InheritableAttr, TargetSpecificAttr { let Spellings = []; let Args = [UnsignedArgument<"Number">]; @@ -660,6 +664,10 @@ def StdCall : InheritableAttr { Keyword<"__stdcall">, Keyword<"_stdcall">]; } +def SysVABI : InheritableAttr { + let Spellings = [GNU<"sysv_abi">, CXX11<"gnu", "sysv_abi">]; +} + def ThisCall : InheritableAttr { let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">, Keyword<"__thiscall">, Keyword<"_thiscall">]; diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index d9d5799e04..91383b76ba 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -205,6 +205,8 @@ namespace clang { CC_X86FastCall, // __attribute__((fastcall)) CC_X86ThisCall, // __attribute__((thiscall)) CC_X86Pascal, // __attribute__((pascal)) + CC_X86_64Win64, // __attribute__((ms_abi)) + CC_X86_64SysV, // __attribute__((sysv_abi)) CC_AAPCS, // __attribute__((pcs("aapcs"))) CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) CC_PnaclCall, // __attribute__((pnaclcall)) diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index 9516a4be99..9fd81337d8 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -920,6 +920,8 @@ struct XMLDumper : public XMLDeclVisitor, case CC_X86StdCall: return set("cc", "x86_stdcall"); case CC_X86ThisCall: return set("cc", "x86_thiscall"); case CC_X86Pascal: return set("cc", "x86_pascal"); + case CC_X86_64Win64: return set("cc", "x86_64_win64"); + case CC_X86_64SysV: return set("cc", "x86_64_sysv"); case CC_AAPCS: return set("cc", "aapcs"); case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); case CC_PnaclCall: return set("cc", "pnaclcall"); diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 97edce105c..78fa543979 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1394,6 +1394,8 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T, switch (CC) { default: llvm_unreachable("Unsupported CC for mangling"); + case CC_X86_64Win64: + case CC_X86_64SysV: case CC_C: Out << 'A'; break; case CC_X86Pascal: Out << 'C'; break; case CC_X86ThisCall: Out << 'E'; break; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1bd2d3b98d..b848d3a224 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1568,6 +1568,8 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86FastCall: return "fastcall"; case CC_X86ThisCall: return "thiscall"; case CC_X86Pascal: return "pascal"; + case CC_X86_64Win64: return "ms_abi"; + case CC_X86_64SysV: return "sysv_abi"; case CC_AAPCS: return "aapcs"; case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_PnaclCall: return "pnaclcall"; @@ -1877,6 +1879,8 @@ bool AttributedType::isCallingConv() const { case attr_stdcall: case attr_thiscall: case attr_pascal: + case attr_ms_abi: + case attr_sysv_abi: case attr_pnaclcall: case attr_inteloclbicc: return true; diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 2a4cf52027..344d12c44f 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -667,6 +667,12 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, case CC_IntelOclBicc: OS << " __attribute__((intel_ocl_bicc))"; break; + case CC_X86_64Win64: + OS << " __attribute__((ms_abi))"; + break; + case CC_X86_64SysV: + OS << " __attribute__((sysv_abi))"; + break; } } @@ -1207,6 +1213,8 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case AttributedType::attr_stdcall: OS << "stdcall"; break; case AttributedType::attr_thiscall: OS << "thiscall"; 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; case AttributedType::attr_pcs: case AttributedType::attr_pcs_vfp: { OS << "pcs("; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index f4c4226482..f588970a87 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -3094,7 +3094,9 @@ public: } virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { - return (CC == CC_C || CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning; + return (CC == CC_C || + CC == CC_IntelOclBicc || + CC == CC_X86_64Win64) ? CCCR_OK : CCCR_Warning; } virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { @@ -3130,6 +3132,11 @@ public: virtual BuiltinVaListKind getBuiltinVaListKind() const { return TargetInfo::CharPtrBuiltinVaList; } + virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { + return (CC == CC_C || + CC == CC_IntelOclBicc || + CC == CC_X86_64SysV) ? CCCR_OK : CCCR_Warning; + } }; } // end anonymous namespace diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index ed02c74cdf..8a67279592 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -41,6 +41,8 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; + case CC_X86_64Win64: return llvm::CallingConv::X86_64_Win64; + case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV; 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; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 92935aed29..2bf56c737a 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3950,6 +3950,16 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { PascalAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); return; + case AttributeList::AT_MSABI: + D->addAttr(::new (S.Context) + MSABIAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); + return; + case AttributeList::AT_SysVABI: + D->addAttr(::new (S.Context) + SysVABIAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); + return; case AttributeList::AT_Pcs: { PcsAttr::PCSType PCS; switch (CC) { @@ -4024,6 +4034,14 @@ 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_MSABI: + CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : + CC_X86_64Win64; + break; + case AttributeList::AT_SysVABI: + CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : + CC_C; + break; case AttributeList::AT_Pcs: { Expr *Arg = attr.getArg(0); StringLiteral *Str = dyn_cast(Arg); @@ -4869,6 +4887,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_FastCall: case AttributeList::AT_ThisCall: case AttributeList::AT_Pascal: + case AttributeList::AT_MSABI: + case AttributeList::AT_SysVABI: case AttributeList::AT_Pcs: case AttributeList::AT_PnaclCall: case AttributeList::AT_IntelOclBicc: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 52b099e197..5834e4f5c7 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -107,6 +107,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_StdCall: \ case AttributeList::AT_ThisCall: \ case AttributeList::AT_Pascal: \ + case AttributeList::AT_MSABI: \ + case AttributeList::AT_SysVABI: \ case AttributeList::AT_Regparm: \ case AttributeList::AT_Pcs: \ case AttributeList::AT_PnaclCall: \ @@ -3405,6 +3407,10 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_PnaclCall; case AttributedType::attr_inteloclbicc: return AttributeList::AT_IntelOclBicc; + case AttributedType::attr_ms_abi: + return AttributeList::AT_MSABI; + case AttributedType::attr_sysv_abi: + return AttributeList::AT_SysVABI; case AttributedType::attr_ptr32: return AttributeList::AT_Ptr32; case AttributedType::attr_ptr64: @@ -4386,6 +4392,10 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { return AttributedType::attr_pnaclcall; case AttributeList::AT_IntelOclBicc: return AttributedType::attr_inteloclbicc; + case AttributeList::AT_MSABI: + return AttributedType::attr_ms_abi; + case AttributeList::AT_SysVABI: + return AttributedType::attr_sysv_abi; } llvm_unreachable("unexpected attribute kind!"); } @@ -4468,7 +4478,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, CallingConv CCOld = fn->getCallConv(); AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr); - if (CC != CCOld) { + if (CCOld != CC) { // Error out on when there's already an attribute on the type // and the CCs don't match. const AttributedType *AT = S.getCallingConvAttributedType(type); diff --git a/test/CodeGen/ms_abi.c b/test/CodeGen/ms_abi.c new file mode 100644 index 0000000000..7c5c26fc41 --- /dev/null +++ b/test/CodeGen/ms_abi.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-freebsd10.0 -emit-llvm < %s | FileCheck -check-prefix=FREEBSD %s +// RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm < %s | FileCheck -check-prefix=WIN64 %s + +void __attribute__((ms_abi)) f1(void); +void __attribute__((sysv_abi)) f2(void); +void f3(void) { +// FREEBSD: define void @f3() +// WIN64: define void @f3() + f1(); +// FREEBSD: call x86_64_win64cc void @f1() +// WIN64: call void @f1() + f2(); +// FREEBSD: call void @f2() +// WIN64: call x86_64_sysvcc void @f2() +} +// FREEBSD: declare x86_64_win64cc void @f1() +// FREEBSD: declare void @f2() +// WIN64: declare void @f1() +// WIN64: declare x86_64_sysvcc void @f2() + diff --git a/test/Sema/callingconv-ms_abi.c b/test/Sema/callingconv-ms_abi.c new file mode 100644 index 0000000000..64c5970adf --- /dev/null +++ b/test/Sema/callingconv-ms_abi.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-win32 %s + +void __attribute__((ms_abi)) foo(void); +void (*pfoo)(void) = foo; + +void __attribute__((sysv_abi)) bar(void); +void (*pbar)(void) = bar; // expected-warning{{incompatible pointer types}} + +void (__attribute__((sysv_abi)) *pfoo2)(void) = foo; // expected-warning{{incompatible pointer types}} diff --git a/test/Sema/callingconv-sysv_abi.c b/test/Sema/callingconv-sysv_abi.c new file mode 100644 index 0000000000..015357d054 --- /dev/null +++ b/test/Sema/callingconv-sysv_abi.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s + +void __attribute__((ms_abi)) foo(void); +void (*pfoo)(void) = foo; // expected-warning{{incompatible pointer types}} + +void __attribute__((sysv_abi)) bar(void); +void (*pbar)(void) = bar; + +void (__attribute__((ms_abi)) *pbar2)(void) = bar; // expected-warning{{incompatible pointer types}} diff --git a/test/Sema/ms_abi-sysv_abi.c b/test/Sema/ms_abi-sysv_abi.c new file mode 100644 index 0000000000..35a5fad9ce --- /dev/null +++ b/test/Sema/ms_abi-sysv_abi.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s + +// CC qualifier can be applied only to functions +int __attribute__((ms_abi)) var1; // expected-warning{{'ms_abi' only applies to function types; type here is 'int'}} +int __attribute__((sysv_abi)) var2; // expected-warning{{'sysv_abi' only applies to function types; type here is 'int'}} + +// Different CC qualifiers are not compatible +// FIXME: Should say 'sysv_abi' instead of 'cdecl' +void __attribute__((ms_abi, sysv_abi)) foo3(void); // expected-error{{cdecl and ms_abi attributes are not compatible}} +void __attribute__((ms_abi)) foo4(); // expected-note{{previous declaration is here}} +void __attribute__((sysv_abi)) foo4(void); // expected-error{{function declared 'cdecl' here was previously declared 'ms_abi'}} + +void bar(int i, int j) __attribute__((ms_abi, cdecl)); // expected-error{{cdecl and ms_abi attributes are not compatible}} +void bar2(int i, int j) __attribute__((sysv_abi, cdecl)); // no-error diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 6c937c6e52..dcf69b5ba4 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -509,6 +509,8 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(X86FastCall); TCALLINGCONV(X86ThisCall); TCALLINGCONV(X86Pascal); + TCALLINGCONV(X86_64Win64); + TCALLINGCONV(X86_64SysV); TCALLINGCONV(AAPCS); TCALLINGCONV(AAPCS_VFP); TCALLINGCONV(PnaclCall);