Author: rjmccall Date: Thu Mar 3 00:39:32 2016 New Revision: 262587 URL: http://llvm.org/viewvc/llvm-project?rev=262587&view=rev Log: Semantic analysis for the swiftcall calling convention.
I've tried to keep the infrastructure behind parameter ABI treatments fairly general. Added: cfe/trunk/test/Sema/attr-swiftcall.c cfe/trunk/test/SemaCXX/attr-swiftcall.cpp Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/include/clang/AST/Attr.h cfe/trunk/include/clang/AST/Type.h cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/AttrDocs.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Basic/Specifiers.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/lib/AST/Type.cpp cfe/trunk/lib/AST/TypePrinter.cpp cfe/trunk/lib/Basic/Targets.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/tools/libclang/CXType.cpp cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Thu Mar 3 00:39:32 2016 @@ -2970,6 +2970,7 @@ enum CXCallingConv { CXCallingConv_X86_64Win64 = 10, CXCallingConv_X86_64SysV = 11, CXCallingConv_X86VectorCall = 12, + CXCallingConv_Swift = 13, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 Modified: cfe/trunk/include/clang/AST/Attr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Attr.h (original) +++ cfe/trunk/include/clang/AST/Attr.h Thu Mar 3 00:39:32 2016 @@ -149,6 +149,36 @@ public: } }; +/// A parameter attribute which changes the argument-passing ABI rule +/// for the parameter. +class ParameterABIAttr : public InheritableParamAttr { +protected: + ParameterABIAttr(attr::Kind AK, SourceRange R, + unsigned SpellingListIndex, bool IsLateParsed, + bool DuplicatesAllowed) + : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed, + DuplicatesAllowed) {} + +public: + ParameterABI getABI() const { + switch (getKind()) { + case attr::SwiftContext: + return ParameterABI::SwiftContext; + case attr::SwiftErrorResult: + return ParameterABI::SwiftErrorResult; + case attr::SwiftIndirectResult: + return ParameterABI::SwiftIndirectResult; + default: + llvm_unreachable("bad parameter ABI attribute kind"); + } + } + + static bool classof(const Attr *A) { + return A->getKind() >= attr::FirstParameterABIAttr && + A->getKind() <= attr::LastParameterABIAttr; + } +}; + #include "clang/AST/Attrs.inc" inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, Modified: cfe/trunk/include/clang/AST/Type.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Type.h (original) +++ cfe/trunk/include/clang/AST/Type.h Thu Mar 3 00:39:32 2016 @@ -3061,12 +3061,23 @@ public: /// not produce the latter. class ExtParameterInfo { enum { - IsConsumed = 0x01, + ABIMask = 0x0F, + IsConsumed = 0x10 }; unsigned char Data; public: ExtParameterInfo() : Data(0) {} + /// Return the ABI treatment of this parameter. + ParameterABI getABI() const { + return ParameterABI(Data & ABIMask); + } + ExtParameterInfo withABI(ParameterABI kind) const { + ExtParameterInfo copy = *this; + copy.Data = (copy.Data & ~ABIMask) | unsigned(kind); + return copy; + } + /// Is this parameter considered "consumed" by Objective-C ARC? /// Consumed parameters must have retainable object type. bool isConsumed() const { @@ -3392,6 +3403,13 @@ public: return ExtParameterInfo(); } + ParameterABI getParameterABI(unsigned I) const { + assert(I < getNumParams() && "parameter index out of range"); + if (hasExtParameterInfos()) + return getExtParameterInfosBuffer()[I].getABI(); + return ParameterABI::Ordinary; + } + bool isParamConsumed(unsigned I) const { assert(I < getNumParams() && "parameter index out of range"); if (hasExtParameterInfos()) @@ -3717,6 +3735,7 @@ public: attr_stdcall, attr_thiscall, attr_pascal, + attr_swiftcall, attr_vectorcall, attr_inteloclbicc, attr_ms_abi, Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Thu Mar 3 00:39:32 2016 @@ -338,6 +338,11 @@ class TargetSpecificAttr<TargetArch targ /// redeclarations, even when it's written on a parameter. class InheritableParamAttr : InheritableAttr; +/// An attribute which changes the ABI rules for a specific parameter. +class ParameterABIAttr : InheritableParamAttr { + let Subjects = SubjectList<[ParmVar]>; +} + /// An ignored attribute, which we parse but discard with no checking. class IgnoredAttr : Attr { let Ignored = 1; @@ -1335,6 +1340,27 @@ def StdCall : InheritableAttr { let Documentation = [StdCallDocs]; } +def SwiftCall : InheritableAttr { + let Spellings = [GCC<"swiftcall">]; +// let Subjects = SubjectList<[Function]>; + let Documentation = [SwiftCallDocs]; +} + +def SwiftContext : ParameterABIAttr { + let Spellings = [GCC<"swift_context">]; + let Documentation = [SwiftContextDocs]; +} + +def SwiftErrorResult : ParameterABIAttr { + let Spellings = [GCC<"swift_error_result">]; + let Documentation = [SwiftErrorResultDocs]; +} + +def SwiftIndirectResult : ParameterABIAttr { + let Spellings = [GCC<"swift_indirect_result">]; + let Documentation = [SwiftIndirectResultDocs]; +} + def SysVABI : InheritableAttr { let Spellings = [GCC<"sysv_abi">]; // let Subjects = [Function, ObjCMethod]; Modified: cfe/trunk/include/clang/Basic/AttrDocs.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/AttrDocs.td (original) +++ cfe/trunk/include/clang/Basic/AttrDocs.td Thu Mar 3 00:39:32 2016 @@ -1958,3 +1958,147 @@ hardware design, touch the red zone. The system will crash if the wrong handler is used. }]; } + +def SwiftCallDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``swiftcall`` attribute indicates that a function should be called +using the Swift calling convention for a function or function pointer. + +The lowering for the Swift calling convention, as described by the Swift +ABI documentation, occurs in multiple phases. The first, "high-level" +phase breaks down the formal parameters and results into innately direct +and indirect components, adds implicit paraameters for the generic +signature, and assigns the context and error ABI treatments to parameters +where applicable. The second phase breaks down the direct parameters +and results from the first phase and assigns them to registers or the +stack. The ``swiftcall`` convention only handles this second phase of +lowering; the C function type must accurately reflect the results +of the first phase, as follows: + +- Results classified as indirect by high-level lowering should be + represented as parameters with the ``swift_indirect_result`` attribute. + +- Results classified as direct by high-level lowering should be represented + as follows: + + - First, remove any empty direct results. + + - If there are no direct results, the C result type should be ``void``. + + - If there is one direct result, the C result type should be a type with + the exact layout of that result type. + + - If there are a multiple direct results, the C result type should be + a struct type with the exact layout of a tuple of those results. + +- Parameters classified as indirect by high-level lowering should be + represented as parameters of pointer type. + +- Parameters classified as direct by high-level lowering should be + omitted if they are empty types; otherwise, they should be represented + as a parameter type with a layout exactly matching the layout of the + Swift parameter type. + +- The context parameter, if present, should be represented as a trailing + parameter with the ``swift_context`` attribute. + +- The error result parameter, if present, should be represented as a + trailing parameter (always following a context parameter) with the + ``swift_error_result`` attribute. + +``swiftcall`` does not support variadic arguments or unprototyped functions. + +The parameter ABI treatment attributes are aspects of the function type. +A function type which which applies an ABI treatment attribute to a +parameter is a different type from an otherwise-identical function type +that does not. A single parameter may not have multiple ABI treatment +attributes. + +Support for this feature is target-dependent, although it should be +supported on every target that Swift supports. Query for this support +with ``__has_attribute(swiftcall)``. This implies support for the +``swift_context``, ``swift_error_result``, and ``swift_indirect_result`` +attributes. + }]; +} + +def SwiftContextDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``swift_context`` attribute marks a parameter of a ``swiftcall`` +function as having the special context-parameter ABI treatment. + +This treatment generally passes the context value in a special register +which is normally callee-preserved. + +A ``swift_context`` parameter must either be the last parameter or must be +followed by a ``swift_error_result`` parameter (which itself must always be +the last parameter). + +A context parameter must have pointer or reference type. + }]; +} + +def SwiftErrorResultDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``swift_error_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special error-result ABI treatment. + +This treatment generally passes the underlying error value in and out of +the function through a special register which is normally callee-preserved. +This is modeled in C by pretending that the register is addressable memory: + +- The caller appears to pass the address of a variable of pointer type. + The current value of this variable is copied into the register before + the call; if the call returns normally, the value is copied back into the + variable. + +- The callee appears to receive the address of a variable. This address + is actually a hidden location in its own stack, initialized with the + value of the register upon entry. When the function returns normally, + the value in that hidden location is written back to the register. + +A ``swift_error_result`` parameter must be the last parameter, and it must be +preceded by a ``swift_context`` parameter. + +A ``swift_error_result`` parameter must have type ``T**`` or ``T*&`` for some +type T. Note that no qualifiers are permitted on the intermediate level. + +It is undefined behavior if the caller does not pass a pointer or +reference to a valid object. + +The standard convention is that the error value itself (that is, the +value stored in the apparent argument) will be null upon function entry, +but this is not enforced by the ABI. + }]; +} + +def SwiftIndirectResultDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special indirect-result ABI treatmenet. + +This treatment gives the parameter the target's normal indirect-result +ABI treatment, which may involve passing it differently from an ordinary +parameter. However, only the first indirect result will receive this +treatment. Furthermore, low-level lowering may decide that a direct result +must be returned indirectly; if so, this will take priority over the +``swift_indirect_result`` parameters. + +A ``swift_indirect_result`` parameter must either be the first parameter or +follow another ``swift_indirect_result`` parameter. + +A ``swift_indirect_result`` parameter must have type ``T*`` or ``T&`` for +some object type ``T``. If ``T`` is a complete type at the point of +definition of a function, it is undefined behavior if the argument +value does not point to storage of adequate size and alignment for a +value of type ``T``. + +Making indirect results explicit in the signature allows C functions to +directly construct objects into them without relying on language +optimizations like C++'s named return value optimization (NRVO). + }]; +} Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Mar 3 00:39:32 2016 @@ -2276,6 +2276,20 @@ def warn_objc_collection_literal_element "object of type %0 is not compatible with " "%select{array element type|dictionary key type|dictionary value type}1 %2">, InGroup<ObjCLiteralConversion>; +def err_swift_param_attr_not_swiftcall : Error< + "'%0' parameter can only be used with swiftcall calling convention">; +def err_swift_indirect_result_not_first : Error< + "'swift_indirect_result' parameters must be first parameters of function">; +def err_swift_context_not_before_swift_error_result : Error< + "'swift_context' parameter can only be followed by 'swift_error_result' " + "parameter">; +def err_swift_error_result_not_last : Error< + "'swift_error_result' parameter must be last parameter of function">; +def err_swift_error_result_not_after_swift_context : Error< + "'swift_error_result' parameter must follow 'swift_context' parameter">; +def err_swift_abi_parameter_wrong_type : Error< + "'%0' parameter must have pointer%select{| to unqualified pointer}1 type; " + "type here is %2">; def err_attribute_argument_is_zero : Error< "%0 attribute must be greater than 0">; Modified: cfe/trunk/include/clang/Basic/Specifiers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Specifiers.h (original) +++ cfe/trunk/include/clang/Basic/Specifiers.h Thu Mar 3 00:39:32 2016 @@ -238,7 +238,8 @@ namespace clang { CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) CC_SpirFunction, // default for OpenCL functions on SPIR target - CC_SpirKernel // inferred for OpenCL kernels on SPIR target + CC_SpirKernel, // inferred for OpenCL kernels on SPIR target + CC_Swift // __attribute__((swiftcall)) }; /// \brief Checks whether the given calling convention supports variadic @@ -252,6 +253,7 @@ namespace clang { case CC_X86VectorCall: case CC_SpirFunction: case CC_SpirKernel: + case CC_Swift: return false; default: return true; @@ -283,6 +285,28 @@ namespace clang { /// Retrieve the spelling of the given nullability kind. llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive = false); + + /// \brief Kinds of parameter ABI. + enum class ParameterABI { + /// This parameter uses ordinary ABI rules for its type. + Ordinary, + + /// This parameter (which must have pointer type) is a Swift + /// indirect result parameter. + SwiftIndirectResult, + + /// This parameter (which must have pointer-to-pointer type) uses + /// the special Swift error-result ABI treatment. There can be at + /// most one parameter on a given function that uses this treatment. + SwiftErrorResult, + + /// This parameter (which must have pointer type) uses the special + /// Swift context-pointer ABI treatment. There can be at + /// most one parameter on a given function that uses this treatment. + SwiftContext + }; + + llvm::StringRef getParameterABISpelling(ParameterABI kind); } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Mar 3 00:39:32 2016 @@ -7789,6 +7789,9 @@ public: void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, unsigned SpellingListIndex, bool InInstantiation = false); + void AddParameterABIAttr(SourceRange AttrRange, Decl *D, + ParameterABI ABI, unsigned SpellingListIndex); + void AddNSConsumedAttr(SourceRange AttrRange, Decl *D, unsigned SpellingListIndex, bool isNSConsumed, bool isTemplateInstantiation); Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Mar 3 00:39:32 2016 @@ -2167,6 +2167,9 @@ StringRef CXXNameMangler::getCallingConv case CC_SpirKernel: // FIXME: we should be mangling all of the above. return ""; + + case CC_Swift: + return "swiftcall"; } llvm_unreachable("bad calling convention"); } @@ -2195,8 +2198,20 @@ CXXNameMangler::mangleExtParameterInfo(F // Note that these are *not* substitution candidates. Demanglers might // have trouble with this if the parameter type is fully substituted. + switch (PI.getABI()) { + case ParameterABI::Ordinary: + break; + + // All of these start with "swift", so they come before "ns_consumed". + case ParameterABI::SwiftContext: + case ParameterABI::SwiftErrorResult: + case ParameterABI::SwiftIndirectResult: + mangleVendorQualifier(getParameterABISpelling(PI.getABI())); + break; + } + if (PI.isConsumed()) - Out << "U11ns_consumed"; + mangleVendorQualifier("ns_consumed"); } // <type> ::= <function-type> Modified: cfe/trunk/lib/AST/Type.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/lib/AST/Type.cpp (original) +++ cfe/trunk/lib/AST/Type.cpp Thu Mar 3 00:39:32 2016 @@ -2655,6 +2655,7 @@ StringRef FunctionType::getNameForCallCo case CC_IntelOclBicc: return "intel_ocl_bicc"; case CC_SpirFunction: return "spir_function"; case CC_SpirKernel: return "spir_kernel"; + case CC_Swift: return "swiftcall"; } llvm_unreachable("Invalid calling convention."); @@ -2995,6 +2996,7 @@ bool AttributedType::isQualifier() const case AttributedType::attr_stdcall: case AttributedType::attr_thiscall: case AttributedType::attr_pascal: + case AttributedType::attr_swiftcall: case AttributedType::attr_vectorcall: case AttributedType::attr_inteloclbicc: case AttributedType::attr_ms_abi: @@ -3048,6 +3050,7 @@ bool AttributedType::isCallingConv() con case attr_fastcall: case attr_stdcall: case attr_thiscall: + case attr_swiftcall: case attr_vectorcall: case attr_pascal: case attr_ms_abi: Modified: cfe/trunk/lib/AST/TypePrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/lib/AST/TypePrinter.cpp (original) +++ cfe/trunk/lib/AST/TypePrinter.cpp Thu Mar 3 00:39:32 2016 @@ -629,6 +629,20 @@ void TypePrinter::printFunctionProtoBefo } } +llvm::StringRef clang::getParameterABISpelling(ParameterABI ABI) { + switch (ABI) { + case ParameterABI::Ordinary: + llvm_unreachable("asking for spelling of ordinary parameter ABI"); + case ParameterABI::SwiftContext: + return "swift_context"; + case ParameterABI::SwiftErrorResult: + return "swift_error_result"; + case ParameterABI::SwiftIndirectResult: + return "swift_indirect_result"; + } + llvm_unreachable("bad parameter ABI kind"); +} + void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, raw_ostream &OS) { // If needed for precedence reasons, wrap the inner part in grouping parens. @@ -644,6 +658,9 @@ void TypePrinter::printFunctionProtoAfte auto EPI = T->getExtParameterInfo(i); if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) "; + auto ABI = EPI.getABI(); + if (ABI != ParameterABI::Ordinary) + OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) "; print(T->getParamType(i), OS, StringRef()); } @@ -707,6 +724,8 @@ void TypePrinter::printFunctionProtoAfte case CC_SpirKernel: // Do nothing. These CCs are not available as attributes. break; + case CC_Swift: + OS << " __attribute__((swiftcall))"; } } @@ -1309,6 +1328,7 @@ void TypePrinter::printAttributedAfter(c case AttributedType::attr_fastcall: OS << "fastcall"; break; case AttributedType::attr_stdcall: OS << "stdcall"; break; case AttributedType::attr_thiscall: OS << "thiscall"; break; + case AttributedType::attr_swiftcall: OS << "swiftcall"; break; case AttributedType::attr_vectorcall: OS << "vectorcall"; break; case AttributedType::attr_pascal: OS << "pascal"; break; case AttributedType::attr_ms_abi: OS << "ms_abi"; break; Modified: cfe/trunk/lib/Basic/Targets.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/lib/Basic/Targets.cpp (original) +++ cfe/trunk/lib/Basic/Targets.cpp Thu Mar 3 00:39:32 2016 @@ -2561,14 +2561,20 @@ public: bool setFPMath(StringRef Name) override; CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { - // We accept all non-ARM calling conventions - return (CC == CC_X86ThisCall || - CC == CC_X86FastCall || - CC == CC_X86StdCall || - CC == CC_X86VectorCall || - CC == CC_C || - CC == CC_X86Pascal || - CC == CC_IntelOclBicc) ? CCCR_OK : CCCR_Warning; + // Most of the non-ARM calling conventions are i386 conventions. + switch (CC) { + case CC_X86ThisCall: + case CC_X86FastCall: + case CC_X86StdCall: + case CC_X86VectorCall: + case CC_C: + case CC_Swift: + case CC_X86Pascal: + case CC_IntelOclBicc: + return CCCR_OK; + default: + return CCCR_Warning; + } } CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { @@ -4111,10 +4117,16 @@ public: } CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { - return (CC == CC_C || - CC == CC_X86VectorCall || - CC == CC_IntelOclBicc || - CC == CC_X86_64Win64) ? CCCR_OK : CCCR_Warning; + switch (CC) { + case CC_C: + case CC_Swift: + case CC_X86VectorCall: + case CC_IntelOclBicc: + case CC_X86_64Win64: + return CCCR_OK; + default: + return CCCR_Warning; + } } CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { @@ -5095,7 +5107,14 @@ public: } CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { - return (CC == CC_AAPCS || CC == CC_AAPCS_VFP) ? CCCR_OK : CCCR_Warning; + switch (CC) { + case CC_AAPCS: + case CC_AAPCS_VFP: + case CC_Swift: + return CCCR_OK; + default: + return CCCR_Warning; + } } int getEHDataRegisterNumber(unsigned RegNo) const override { @@ -5547,6 +5566,16 @@ public: return true; } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + case CC_C: + case CC_Swift: + return CCCR_OK; + default: + return CCCR_Warning; + } + } + bool isCLZForZeroUndef() const override { return false; } BuiltinVaListKind getBuiltinVaListKind() const override { Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Mar 3 00:39:32 2016 @@ -3728,6 +3728,11 @@ static void handleCallConvAttr(Sema &S, PascalAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); return; + case AttributeList::AT_SwiftCall: + D->addAttr(::new (S.Context) + SwiftCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); + return; case AttributeList::AT_VectorCall: D->addAttr(::new (S.Context) VectorCallAttr(Attr.getRange(), S.Context, @@ -3795,6 +3800,7 @@ bool Sema::CheckCallingConvAttr(const At 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_SwiftCall: CC = CC_Swift; break; case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break; case AttributeList::AT_MSABI: CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : @@ -3845,6 +3851,96 @@ bool Sema::CheckCallingConvAttr(const At return false; } +/// Pointer-like types in the default address space. +static bool isValidSwiftContextType(QualType type) { + if (!type->hasPointerRepresentation()) + return type->isDependentType(); + return type->getPointeeType().getAddressSpace() == 0; +} + +/// Pointers and references in the default address space. +static bool isValidSwiftIndirectResultType(QualType type) { + if (auto ptrType = type->getAs<PointerType>()) { + type = ptrType->getPointeeType(); + } else if (auto refType = type->getAs<ReferenceType>()) { + type = refType->getPointeeType(); + } else { + return type->isDependentType(); + } + return type.getAddressSpace() == 0; +} + +/// Pointers and references to pointers in the default address space. +static bool isValidSwiftErrorResultType(QualType type) { + if (auto ptrType = type->getAs<PointerType>()) { + type = ptrType->getPointeeType(); + } else if (auto refType = type->getAs<ReferenceType>()) { + type = refType->getPointeeType(); + } else { + return type->isDependentType(); + } + if (!type.getQualifiers().empty()) + return false; + return isValidSwiftContextType(type); +} + +static void handleParameterABIAttr(Sema &S, Decl *D, const AttributeList &attr, + ParameterABI abi) { + S.AddParameterABIAttr(attr.getRange(), D, abi, + attr.getAttributeSpellingListIndex()); +} + +void Sema::AddParameterABIAttr(SourceRange range, Decl *D, ParameterABI abi, + unsigned spellingIndex) { + + QualType type = cast<ParmVarDecl>(D)->getType(); + + if (auto existingAttr = D->getAttr<ParameterABIAttr>()) { + if (existingAttr->getABI() != abi) { + Diag(range.getBegin(), diag::err_attributes_are_not_compatible) + << getParameterABISpelling(abi) << existingAttr; + Diag(existingAttr->getLocation(), diag::note_conflicting_attribute); + return; + } + } + + switch (abi) { + case ParameterABI::Ordinary: + llvm_unreachable("explicit attribute for ordinary parameter ABI?"); + + case ParameterABI::SwiftContext: + if (!isValidSwiftContextType(type)) { + Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type) + << getParameterABISpelling(abi) + << /*pointer to pointer */ 0 << type; + } + D->addAttr(::new (Context) + SwiftContextAttr(range, Context, spellingIndex)); + return; + + case ParameterABI::SwiftErrorResult: + if (!isValidSwiftErrorResultType(type)) { + Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type) + << getParameterABISpelling(abi) + << /*pointer to pointer */ 1 << type; + } + D->addAttr(::new (Context) + SwiftErrorResultAttr(range, Context, spellingIndex)); + return; + + case ParameterABI::SwiftIndirectResult: + if (!isValidSwiftIndirectResultType(type)) { + Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type) + << getParameterABISpelling(abi) + << /*pointer*/ 0 << type; + } + D->addAttr(::new (Context) + SwiftIndirectResultAttr(range, Context, spellingIndex)); + return; + } + llvm_unreachable("bad parameter ABI attribute"); +} + /// Checks a regparm attribute, returning true if it is ill-formed and /// otherwise setting numParams to the appropriate value. bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { @@ -5484,6 +5580,7 @@ static void ProcessDeclAttribute(Sema &S case AttributeList::AT_FastCall: case AttributeList::AT_ThisCall: case AttributeList::AT_Pascal: + case AttributeList::AT_SwiftCall: case AttributeList::AT_VectorCall: case AttributeList::AT_MSABI: case AttributeList::AT_SysVABI: @@ -5497,6 +5594,15 @@ static void ProcessDeclAttribute(Sema &S case AttributeList::AT_OpenCLAccess: handleOpenCLAccessAttr(S, D, Attr); break; + case AttributeList::AT_SwiftContext: + handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftContext); + break; + case AttributeList::AT_SwiftErrorResult: + handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftErrorResult); + break; + case AttributeList::AT_SwiftIndirectResult: + handleParameterABIAttr(S, D, Attr, ParameterABI::SwiftIndirectResult); + break; case AttributeList::AT_InternalLinkage: handleInternalLinkageAttr(S, D, Attr); break; Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Mar 3 00:39:32 2016 @@ -286,6 +286,12 @@ void Sema::InstantiateAttrs(const MultiL } } + if (auto ABIAttr = dyn_cast<ParameterABIAttr>(TmplAttr)) { + AddParameterABIAttr(ABIAttr->getRange(), New, ABIAttr->getABI(), + ABIAttr->getSpellingListIndex()); + continue; + } + if (isa<NSConsumedAttr>(TmplAttr) || isa<CFConsumedAttr>(TmplAttr)) { AddNSConsumedAttr(TmplAttr->getRange(), New, TmplAttr->getSpellingListIndex(), Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Thu Mar 3 00:39:32 2016 @@ -107,6 +107,7 @@ static void diagnoseBadTypeAttribute(Sem case AttributeList::AT_StdCall: \ case AttributeList::AT_ThisCall: \ case AttributeList::AT_Pascal: \ + case AttributeList::AT_SwiftCall: \ case AttributeList::AT_VectorCall: \ case AttributeList::AT_MSABI: \ case AttributeList::AT_SysVABI: \ @@ -2268,6 +2269,74 @@ bool Sema::CheckFunctionReturnType(QualT return false; } +/// Check the extended parameter information. Most of the necessary +/// checking should occur when applying the parameter attribute; the +/// only other checks required are positional restrictions. +static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes, + const FunctionProtoType::ExtProtoInfo &EPI, + llvm::function_ref<SourceLocation(unsigned)> getParamLoc) { + assert(EPI.ExtParameterInfos && "shouldn't get here without param infos"); + + bool hasCheckedSwiftCall = false; + auto checkForSwiftCC = [&](unsigned paramIndex) { + // Only do this once. + if (hasCheckedSwiftCall) return; + hasCheckedSwiftCall = true; + if (EPI.ExtInfo.getCC() == CC_Swift) return; + S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall) + << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI()); + }; + + for (size_t paramIndex = 0, numParams = paramTypes.size(); + paramIndex != numParams; ++paramIndex) { + switch (EPI.ExtParameterInfos[paramIndex].getABI()) { + // Nothing interesting to check for orindary-ABI parameters. + case ParameterABI::Ordinary: + continue; + + // swift_indirect_result parameters must be a prefix of the function + // arguments. + case ParameterABI::SwiftIndirectResult: + checkForSwiftCC(paramIndex); + if (paramIndex != 0 && + EPI.ExtParameterInfos[paramIndex - 1].getABI() + != ParameterABI::SwiftIndirectResult) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_indirect_result_not_first); + } + continue; + + // swift_context parameters must be the last parameter except for + // a possible swift_error parameter. + case ParameterABI::SwiftContext: + checkForSwiftCC(paramIndex); + if (!(paramIndex == numParams - 1 || + (paramIndex == numParams - 2 && + EPI.ExtParameterInfos[numParams - 1].getABI() + == ParameterABI::SwiftErrorResult))) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_context_not_before_swift_error_result); + } + continue; + + // swift_error parameters must be the last parameter. + case ParameterABI::SwiftErrorResult: + checkForSwiftCC(paramIndex); + if (paramIndex != numParams - 1) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_error_result_not_last); + } else if (paramIndex == 0 || + EPI.ExtParameterInfos[paramIndex - 1].getABI() + != ParameterABI::SwiftContext) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_error_result_not_after_swift_context); + } + continue; + } + llvm_unreachable("bad ABI kind"); + } +} + QualType Sema::BuildFunctionType(QualType T, MutableArrayRef<QualType> ParamTypes, SourceLocation Loc, DeclarationName Entity, @@ -2292,6 +2361,11 @@ QualType Sema::BuildFunctionType(QualTyp ParamTypes[Idx] = ParamType; } + if (EPI.ExtParameterInfos) { + checkExtParameterInfos(*this, ParamTypes, EPI, + [=](unsigned i) { return Loc; }); + } + if (Invalid) return QualType(); @@ -4071,11 +4145,20 @@ static TypeSourceInfo *GetFullTypeForDec HasAnyInterestingExtParameterInfos = true; } + if (auto attr = Param->getAttr<ParameterABIAttr>()) { + ExtParameterInfos[i] = + ExtParameterInfos[i].withABI(attr->getABI()); + HasAnyInterestingExtParameterInfos = true; + } + ParamTys.push_back(ParamTy); } - if (HasAnyInterestingExtParameterInfos) + if (HasAnyInterestingExtParameterInfos) { EPI.ExtParameterInfos = ExtParameterInfos.data(); + checkExtParameterInfos(S, ParamTys, EPI, + [&](unsigned i) { return FTI.Params[i].Param->getLocation(); }); + } SmallVector<QualType, 4> Exceptions; SmallVector<ParsedType, 2> DynamicExceptions; @@ -4534,6 +4617,8 @@ static AttributeList::Kind getAttrListKi return AttributeList::AT_ThisCall; case AttributedType::attr_pascal: return AttributeList::AT_Pascal; + case AttributedType::attr_swiftcall: + return AttributeList::AT_SwiftCall; case AttributedType::attr_vectorcall: return AttributeList::AT_VectorCall; case AttributedType::attr_pcs: @@ -5857,6 +5942,8 @@ static AttributedType::Kind getCCTypeAtt return AttributedType::attr_thiscall; case AttributeList::AT_Pascal: return AttributedType::attr_pascal; + case AttributeList::AT_SwiftCall: + return AttributedType::attr_swiftcall; case AttributeList::AT_VectorCall: return AttributedType::attr_vectorcall; case AttributeList::AT_Pcs: { Added: cfe/trunk/test/Sema/attr-swiftcall.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-swiftcall.c?rev=262587&view=auto ============================================================================== --- cfe/trunk/test/Sema/attr-swiftcall.c (added) +++ cfe/trunk/test/Sema/attr-swiftcall.c Thu Mar 3 00:39:32 2016 @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s + +#define SWIFTCALL __attribute__((swiftcall)) +#define INDIRECT_RESULT __attribute__((swift_indirect_result)) +#define ERROR_RESULT __attribute__((swift_error_result)) +#define CONTEXT __attribute__((swift_context)) + +int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} +void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} +void unprototyped() SWIFTCALL; // expected-error {{function with no prototype cannot use the swiftcall calling convention}} +void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} +void (*functionPointer)(void) SWIFTCALL; + +void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} +void indirect_result_bad_position(int first, INDIRECT_RESULT void *out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameters must be first parameters of function}} +void indirect_result_bad_type(INDIRECT_RESULT int out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameter must have pointer type; type here is 'int'}} +void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL; +void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL; + +void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}} +void error_result_bad_position(ERROR_RESULT void **error, int last) SWIFTCALL; // expected-error {{'swift_error_result' parameter must be last parameter of function}} +void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}} +void error_result_bad_type(CONTEXT void *context, ERROR_RESULT int error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int'}} +void error_result_bad_type2(CONTEXT void *context, ERROR_RESULT int *error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int *'}} +void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL; + +void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}} +void context_bad_position(CONTEXT void *context, int x) SWIFTCALL; // expected-error {{'swift_context' parameter can only be followed by 'swift_error_result' parameter}} +void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}} +void context_okay(CONTEXT void *context) SWIFTCALL; Added: cfe/trunk/test/SemaCXX/attr-swiftcall.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-swiftcall.cpp?rev=262587&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/attr-swiftcall.cpp (added) +++ cfe/trunk/test/SemaCXX/attr-swiftcall.cpp Thu Mar 3 00:39:32 2016 @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s + +#define SWIFTCALL __attribute__((swiftcall)) +#define INDIRECT_RESULT __attribute__((swift_indirect_result)) +#define ERROR_RESULT __attribute__((swift_error_result)) +#define CONTEXT __attribute__((swift_context)) + +int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}} +void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}} +void multiple_ccs(int x) SWIFTCALL __attribute__((vectorcall)); // expected-error {{vectorcall and swiftcall attributes are not compatible}} +void (*functionPointer)(void) SWIFTCALL; + +void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}} +void indirect_result_bad_position(int first, INDIRECT_RESULT void *out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameters must be first parameters of function}} +void indirect_result_bad_type(INDIRECT_RESULT int out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameter must have pointer type; type here is 'int'}} +void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL; +void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL; + +void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}} +void error_result_bad_position(ERROR_RESULT void **error, int last) SWIFTCALL; // expected-error {{'swift_error_result' parameter must be last parameter of function}} +void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}} +void error_result_bad_type(CONTEXT void *context, ERROR_RESULT int error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int'}} +void error_result_bad_type2(CONTEXT void *context, ERROR_RESULT int *error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int *'}} +void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL; + +void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}} +void context_bad_position(CONTEXT void *context, int x) SWIFTCALL; // expected-error {{'swift_context' parameter can only be followed by 'swift_error_result' parameter}} +void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}} +void context_okay(CONTEXT void *context) SWIFTCALL; + +template <class T> void indirect_result_temp_okay1(INDIRECT_RESULT T *out) SWIFTCALL; +template <class T> void indirect_result_temp_okay2(INDIRECT_RESULT T out) SWIFTCALL; // expected-note {{candidate template ignored: substitution failure [with T = int]: 'swift_indirect_result' parameter must have pointer type; type here is 'int'}} +void test_indirect_result_temp(void *out) { + indirect_result_temp_okay1(out); + indirect_result_temp_okay2(out); + indirect_result_temp_okay2(1); // expected-error {{no matching function for call to 'indirect_result_temp_okay2'}} +} Modified: cfe/trunk/tools/libclang/CXType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXType.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CXType.cpp (original) +++ cfe/trunk/tools/libclang/CXType.cpp Thu Mar 3 00:39:32 2016 @@ -533,6 +533,7 @@ CXCallingConv clang_getFunctionTypeCalli TCALLINGCONV(AAPCS); TCALLINGCONV(AAPCS_VFP); TCALLINGCONV(IntelOclBicc); + TCALLINGCONV(Swift); case CC_SpirFunction: return CXCallingConv_Unexposed; case CC_SpirKernel: return CXCallingConv_Unexposed; break; Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=262587&r1=262586&r2=262587&view=diff ============================================================================== --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original) +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Thu Mar 3 00:39:32 2016 @@ -1762,7 +1762,8 @@ namespace { static const AttrClassDescriptor AttrClassDescriptors[] = { { "ATTR", "Attr" }, { "INHERITABLE_ATTR", "InheritableAttr" }, - { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" } + { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" }, + { "PARAMETER_ABI_ATTR", "ParameterABIAttr" } }; static void emitDefaultDefine(raw_ostream &OS, StringRef name, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits