CXCallingConv_X86_64Win64 = 10,
CXCallingConv_X86_64SysV = 11,
CXCallingConv_X86VectorCall = 12,
+ CXCallingConv_Swift = 13,
CXCallingConv_Invalid = 100,
CXCallingConv_Unexposed = 200
}
};
+/// 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,
/// 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 {
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())
attr_stdcall,
attr_thiscall,
attr_pascal,
+ attr_swiftcall,
attr_vectorcall,
attr_inteloclbicc,
attr_ms_abi,
/// 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;
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];
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).
+ }];
+}
"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">;
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
case CC_X86VectorCall:
case CC_SpirFunction:
case CC_SpirKernel:
+ case CC_Swift:
return false;
default:
return true;
/// 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
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);
case CC_SpirKernel:
// FIXME: we should be mangling all of the above.
return "";
+
+ case CC_Swift:
+ return "swiftcall";
}
llvm_unreachable("bad calling convention");
}
// 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>
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.");
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:
case attr_fastcall:
case attr_stdcall:
case attr_thiscall:
+ case attr_swiftcall:
case attr_vectorcall:
case attr_pascal:
case attr_ms_abi:
}
}
+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.
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());
}
case CC_SpirKernel:
// Do nothing. These CCs are not available as attributes.
break;
+ case CC_Swift:
+ OS << " __attribute__((swiftcall))";
}
}
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;
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 {
}
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 {
}
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 {
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 {
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,
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 :
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) {
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:
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;
}
}
+ 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(),
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: \
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,
ParamTypes[Idx] = ParamType;
}
+ if (EPI.ExtParameterInfos) {
+ checkExtParameterInfos(*this, ParamTypes, EPI,
+ [=](unsigned i) { return Loc; });
+ }
+
if (Invalid)
return QualType();
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;
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:
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: {
--- /dev/null
+// 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;
--- /dev/null
+// 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'}}
+}
TCALLINGCONV(AAPCS);
TCALLINGCONV(AAPCS_VFP);
TCALLINGCONV(IntelOclBicc);
+ TCALLINGCONV(Swift);
case CC_SpirFunction: return CXCallingConv_Unexposed;
case CC_SpirKernel: return CXCallingConv_Unexposed;
break;
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,