Skip to content

Commit 477f2bb

Browse files
committedMar 3, 2016
Semantic analysis for the swiftcall calling convention.
I've tried to keep the infrastructure behind parameter ABI treatments fairly general. llvm-svn: 262587
1 parent eb3413e commit 477f2bb

19 files changed

+614
-18
lines changed
 

‎clang/include/clang-c/Index.h

+1
Original file line numberDiff line numberDiff line change
@@ -2970,6 +2970,7 @@ enum CXCallingConv {
29702970
CXCallingConv_X86_64Win64 = 10,
29712971
CXCallingConv_X86_64SysV = 11,
29722972
CXCallingConv_X86VectorCall = 12,
2973+
CXCallingConv_Swift = 13,
29732974

29742975
CXCallingConv_Invalid = 100,
29752976
CXCallingConv_Unexposed = 200

‎clang/include/clang/AST/Attr.h

+30
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,36 @@ class InheritableParamAttr : public InheritableAttr {
149149
}
150150
};
151151

152+
/// A parameter attribute which changes the argument-passing ABI rule
153+
/// for the parameter.
154+
class ParameterABIAttr : public InheritableParamAttr {
155+
protected:
156+
ParameterABIAttr(attr::Kind AK, SourceRange R,
157+
unsigned SpellingListIndex, bool IsLateParsed,
158+
bool DuplicatesAllowed)
159+
: InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed,
160+
DuplicatesAllowed) {}
161+
162+
public:
163+
ParameterABI getABI() const {
164+
switch (getKind()) {
165+
case attr::SwiftContext:
166+
return ParameterABI::SwiftContext;
167+
case attr::SwiftErrorResult:
168+
return ParameterABI::SwiftErrorResult;
169+
case attr::SwiftIndirectResult:
170+
return ParameterABI::SwiftIndirectResult;
171+
default:
172+
llvm_unreachable("bad parameter ABI attribute kind");
173+
}
174+
}
175+
176+
static bool classof(const Attr *A) {
177+
return A->getKind() >= attr::FirstParameterABIAttr &&
178+
A->getKind() <= attr::LastParameterABIAttr;
179+
}
180+
};
181+
152182
#include "clang/AST/Attrs.inc"
153183

154184
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,

‎clang/include/clang/AST/Type.h

+20-1
Original file line numberDiff line numberDiff line change
@@ -3061,12 +3061,23 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
30613061
/// not produce the latter.
30623062
class ExtParameterInfo {
30633063
enum {
3064-
IsConsumed = 0x01,
3064+
ABIMask = 0x0F,
3065+
IsConsumed = 0x10
30653066
};
30663067
unsigned char Data;
30673068
public:
30683069
ExtParameterInfo() : Data(0) {}
30693070

3071+
/// Return the ABI treatment of this parameter.
3072+
ParameterABI getABI() const {
3073+
return ParameterABI(Data & ABIMask);
3074+
}
3075+
ExtParameterInfo withABI(ParameterABI kind) const {
3076+
ExtParameterInfo copy = *this;
3077+
copy.Data = (copy.Data & ~ABIMask) | unsigned(kind);
3078+
return copy;
3079+
}
3080+
30703081
/// Is this parameter considered "consumed" by Objective-C ARC?
30713082
/// Consumed parameters must have retainable object type.
30723083
bool isConsumed() const {
@@ -3392,6 +3403,13 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
33923403
return ExtParameterInfo();
33933404
}
33943405

3406+
ParameterABI getParameterABI(unsigned I) const {
3407+
assert(I < getNumParams() && "parameter index out of range");
3408+
if (hasExtParameterInfos())
3409+
return getExtParameterInfosBuffer()[I].getABI();
3410+
return ParameterABI::Ordinary;
3411+
}
3412+
33953413
bool isParamConsumed(unsigned I) const {
33963414
assert(I < getNumParams() && "parameter index out of range");
33973415
if (hasExtParameterInfos())
@@ -3717,6 +3735,7 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
37173735
attr_stdcall,
37183736
attr_thiscall,
37193737
attr_pascal,
3738+
attr_swiftcall,
37203739
attr_vectorcall,
37213740
attr_inteloclbicc,
37223741
attr_ms_abi,

‎clang/include/clang/Basic/Attr.td

+26
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ class TargetSpecificAttr<TargetArch target> {
338338
/// redeclarations, even when it's written on a parameter.
339339
class InheritableParamAttr : InheritableAttr;
340340

341+
/// An attribute which changes the ABI rules for a specific parameter.
342+
class ParameterABIAttr : InheritableParamAttr {
343+
let Subjects = SubjectList<[ParmVar]>;
344+
}
345+
341346
/// An ignored attribute, which we parse but discard with no checking.
342347
class IgnoredAttr : Attr {
343348
let Ignored = 1;
@@ -1335,6 +1340,27 @@ def StdCall : InheritableAttr {
13351340
let Documentation = [StdCallDocs];
13361341
}
13371342

1343+
def SwiftCall : InheritableAttr {
1344+
let Spellings = [GCC<"swiftcall">];
1345+
// let Subjects = SubjectList<[Function]>;
1346+
let Documentation = [SwiftCallDocs];
1347+
}
1348+
1349+
def SwiftContext : ParameterABIAttr {
1350+
let Spellings = [GCC<"swift_context">];
1351+
let Documentation = [SwiftContextDocs];
1352+
}
1353+
1354+
def SwiftErrorResult : ParameterABIAttr {
1355+
let Spellings = [GCC<"swift_error_result">];
1356+
let Documentation = [SwiftErrorResultDocs];
1357+
}
1358+
1359+
def SwiftIndirectResult : ParameterABIAttr {
1360+
let Spellings = [GCC<"swift_indirect_result">];
1361+
let Documentation = [SwiftIndirectResultDocs];
1362+
}
1363+
13381364
def SysVABI : InheritableAttr {
13391365
let Spellings = [GCC<"sysv_abi">];
13401366
// let Subjects = [Function, ObjCMethod];

‎clang/include/clang/Basic/AttrDocs.td

+144
Original file line numberDiff line numberDiff line change
@@ -1958,3 +1958,147 @@ hardware design, touch the red zone.
19581958
The system will crash if the wrong handler is used.
19591959
}];
19601960
}
1961+
1962+
def SwiftCallDocs : Documentation {
1963+
let Category = DocCatVariable;
1964+
let Content = [{
1965+
The ``swiftcall`` attribute indicates that a function should be called
1966+
using the Swift calling convention for a function or function pointer.
1967+
1968+
The lowering for the Swift calling convention, as described by the Swift
1969+
ABI documentation, occurs in multiple phases. The first, "high-level"
1970+
phase breaks down the formal parameters and results into innately direct
1971+
and indirect components, adds implicit paraameters for the generic
1972+
signature, and assigns the context and error ABI treatments to parameters
1973+
where applicable. The second phase breaks down the direct parameters
1974+
and results from the first phase and assigns them to registers or the
1975+
stack. The ``swiftcall`` convention only handles this second phase of
1976+
lowering; the C function type must accurately reflect the results
1977+
of the first phase, as follows:
1978+
1979+
- Results classified as indirect by high-level lowering should be
1980+
represented as parameters with the ``swift_indirect_result`` attribute.
1981+
1982+
- Results classified as direct by high-level lowering should be represented
1983+
as follows:
1984+
1985+
- First, remove any empty direct results.
1986+
1987+
- If there are no direct results, the C result type should be ``void``.
1988+
1989+
- If there is one direct result, the C result type should be a type with
1990+
the exact layout of that result type.
1991+
1992+
- If there are a multiple direct results, the C result type should be
1993+
a struct type with the exact layout of a tuple of those results.
1994+
1995+
- Parameters classified as indirect by high-level lowering should be
1996+
represented as parameters of pointer type.
1997+
1998+
- Parameters classified as direct by high-level lowering should be
1999+
omitted if they are empty types; otherwise, they should be represented
2000+
as a parameter type with a layout exactly matching the layout of the
2001+
Swift parameter type.
2002+
2003+
- The context parameter, if present, should be represented as a trailing
2004+
parameter with the ``swift_context`` attribute.
2005+
2006+
- The error result parameter, if present, should be represented as a
2007+
trailing parameter (always following a context parameter) with the
2008+
``swift_error_result`` attribute.
2009+
2010+
``swiftcall`` does not support variadic arguments or unprototyped functions.
2011+
2012+
The parameter ABI treatment attributes are aspects of the function type.
2013+
A function type which which applies an ABI treatment attribute to a
2014+
parameter is a different type from an otherwise-identical function type
2015+
that does not. A single parameter may not have multiple ABI treatment
2016+
attributes.
2017+
2018+
Support for this feature is target-dependent, although it should be
2019+
supported on every target that Swift supports. Query for this support
2020+
with ``__has_attribute(swiftcall)``. This implies support for the
2021+
``swift_context``, ``swift_error_result``, and ``swift_indirect_result``
2022+
attributes.
2023+
}];
2024+
}
2025+
2026+
def SwiftContextDocs : Documentation {
2027+
let Category = DocCatVariable;
2028+
let Content = [{
2029+
The ``swift_context`` attribute marks a parameter of a ``swiftcall``
2030+
function as having the special context-parameter ABI treatment.
2031+
2032+
This treatment generally passes the context value in a special register
2033+
which is normally callee-preserved.
2034+
2035+
A ``swift_context`` parameter must either be the last parameter or must be
2036+
followed by a ``swift_error_result`` parameter (which itself must always be
2037+
the last parameter).
2038+
2039+
A context parameter must have pointer or reference type.
2040+
}];
2041+
}
2042+
2043+
def SwiftErrorResultDocs : Documentation {
2044+
let Category = DocCatVariable;
2045+
let Content = [{
2046+
The ``swift_error_result`` attribute marks a parameter of a ``swiftcall``
2047+
function as having the special error-result ABI treatment.
2048+
2049+
This treatment generally passes the underlying error value in and out of
2050+
the function through a special register which is normally callee-preserved.
2051+
This is modeled in C by pretending that the register is addressable memory:
2052+
2053+
- The caller appears to pass the address of a variable of pointer type.
2054+
The current value of this variable is copied into the register before
2055+
the call; if the call returns normally, the value is copied back into the
2056+
variable.
2057+
2058+
- The callee appears to receive the address of a variable. This address
2059+
is actually a hidden location in its own stack, initialized with the
2060+
value of the register upon entry. When the function returns normally,
2061+
the value in that hidden location is written back to the register.
2062+
2063+
A ``swift_error_result`` parameter must be the last parameter, and it must be
2064+
preceded by a ``swift_context`` parameter.
2065+
2066+
A ``swift_error_result`` parameter must have type ``T**`` or ``T*&`` for some
2067+
type T. Note that no qualifiers are permitted on the intermediate level.
2068+
2069+
It is undefined behavior if the caller does not pass a pointer or
2070+
reference to a valid object.
2071+
2072+
The standard convention is that the error value itself (that is, the
2073+
value stored in the apparent argument) will be null upon function entry,
2074+
but this is not enforced by the ABI.
2075+
}];
2076+
}
2077+
2078+
def SwiftIndirectResultDocs : Documentation {
2079+
let Category = DocCatVariable;
2080+
let Content = [{
2081+
The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall``
2082+
function as having the special indirect-result ABI treatmenet.
2083+
2084+
This treatment gives the parameter the target's normal indirect-result
2085+
ABI treatment, which may involve passing it differently from an ordinary
2086+
parameter. However, only the first indirect result will receive this
2087+
treatment. Furthermore, low-level lowering may decide that a direct result
2088+
must be returned indirectly; if so, this will take priority over the
2089+
``swift_indirect_result`` parameters.
2090+
2091+
A ``swift_indirect_result`` parameter must either be the first parameter or
2092+
follow another ``swift_indirect_result`` parameter.
2093+
2094+
A ``swift_indirect_result`` parameter must have type ``T*`` or ``T&`` for
2095+
some object type ``T``. If ``T`` is a complete type at the point of
2096+
definition of a function, it is undefined behavior if the argument
2097+
value does not point to storage of adequate size and alignment for a
2098+
value of type ``T``.
2099+
2100+
Making indirect results explicit in the signature allows C functions to
2101+
directly construct objects into them without relying on language
2102+
optimizations like C++'s named return value optimization (NRVO).
2103+
}];
2104+
}

‎clang/include/clang/Basic/DiagnosticSemaKinds.td

+14
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,20 @@ def warn_objc_collection_literal_element : Warning<
22762276
"object of type %0 is not compatible with "
22772277
"%select{array element type|dictionary key type|dictionary value type}1 %2">,
22782278
InGroup<ObjCLiteralConversion>;
2279+
def err_swift_param_attr_not_swiftcall : Error<
2280+
"'%0' parameter can only be used with swiftcall calling convention">;
2281+
def err_swift_indirect_result_not_first : Error<
2282+
"'swift_indirect_result' parameters must be first parameters of function">;
2283+
def err_swift_context_not_before_swift_error_result : Error<
2284+
"'swift_context' parameter can only be followed by 'swift_error_result' "
2285+
"parameter">;
2286+
def err_swift_error_result_not_last : Error<
2287+
"'swift_error_result' parameter must be last parameter of function">;
2288+
def err_swift_error_result_not_after_swift_context : Error<
2289+
"'swift_error_result' parameter must follow 'swift_context' parameter">;
2290+
def err_swift_abi_parameter_wrong_type : Error<
2291+
"'%0' parameter must have pointer%select{| to unqualified pointer}1 type; "
2292+
"type here is %2">;
22792293

22802294
def err_attribute_argument_is_zero : Error<
22812295
"%0 attribute must be greater than 0">;

‎clang/include/clang/Basic/Specifiers.h

+25-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ namespace clang {
238238
CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
239239
CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
240240
CC_SpirFunction, // default for OpenCL functions on SPIR target
241-
CC_SpirKernel // inferred for OpenCL kernels on SPIR target
241+
CC_SpirKernel, // inferred for OpenCL kernels on SPIR target
242+
CC_Swift // __attribute__((swiftcall))
242243
};
243244

244245
/// \brief Checks whether the given calling convention supports variadic
@@ -252,6 +253,7 @@ namespace clang {
252253
case CC_X86VectorCall:
253254
case CC_SpirFunction:
254255
case CC_SpirKernel:
256+
case CC_Swift:
255257
return false;
256258
default:
257259
return true;
@@ -283,6 +285,28 @@ namespace clang {
283285
/// Retrieve the spelling of the given nullability kind.
284286
llvm::StringRef getNullabilitySpelling(NullabilityKind kind,
285287
bool isContextSensitive = false);
288+
289+
/// \brief Kinds of parameter ABI.
290+
enum class ParameterABI {
291+
/// This parameter uses ordinary ABI rules for its type.
292+
Ordinary,
293+
294+
/// This parameter (which must have pointer type) is a Swift
295+
/// indirect result parameter.
296+
SwiftIndirectResult,
297+
298+
/// This parameter (which must have pointer-to-pointer type) uses
299+
/// the special Swift error-result ABI treatment. There can be at
300+
/// most one parameter on a given function that uses this treatment.
301+
SwiftErrorResult,
302+
303+
/// This parameter (which must have pointer type) uses the special
304+
/// Swift context-pointer ABI treatment. There can be at
305+
/// most one parameter on a given function that uses this treatment.
306+
SwiftContext
307+
};
308+
309+
llvm::StringRef getParameterABISpelling(ParameterABI kind);
286310
} // end namespace clang
287311

288312
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H

‎clang/include/clang/Sema/Sema.h

+3
Original file line numberDiff line numberDiff line change
@@ -7789,6 +7789,9 @@ class Sema {
77897789
void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
77907790
unsigned SpellingListIndex, bool InInstantiation = false);
77917791

7792+
void AddParameterABIAttr(SourceRange AttrRange, Decl *D,
7793+
ParameterABI ABI, unsigned SpellingListIndex);
7794+
77927795
void AddNSConsumedAttr(SourceRange AttrRange, Decl *D,
77937796
unsigned SpellingListIndex, bool isNSConsumed,
77947797
bool isTemplateInstantiation);

‎clang/lib/AST/ItaniumMangle.cpp

+16-1
Original file line numberDiff line numberDiff line change
@@ -2167,6 +2167,9 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
21672167
case CC_SpirKernel:
21682168
// FIXME: we should be mangling all of the above.
21692169
return "";
2170+
2171+
case CC_Swift:
2172+
return "swiftcall";
21702173
}
21712174
llvm_unreachable("bad calling convention");
21722175
}
@@ -2195,8 +2198,20 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
21952198
// Note that these are *not* substitution candidates. Demanglers might
21962199
// have trouble with this if the parameter type is fully substituted.
21972200

2201+
switch (PI.getABI()) {
2202+
case ParameterABI::Ordinary:
2203+
break;
2204+
2205+
// All of these start with "swift", so they come before "ns_consumed".
2206+
case ParameterABI::SwiftContext:
2207+
case ParameterABI::SwiftErrorResult:
2208+
case ParameterABI::SwiftIndirectResult:
2209+
mangleVendorQualifier(getParameterABISpelling(PI.getABI()));
2210+
break;
2211+
}
2212+
21982213
if (PI.isConsumed())
2199-
Out << "U11ns_consumed";
2214+
mangleVendorQualifier("ns_consumed");
22002215
}
22012216

22022217
// <type> ::= <function-type>

0 commit comments

Comments
 (0)