mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
164 lines
5.7 KiB
ReStructuredText
164 lines
5.7 KiB
ReStructuredText
:orphan:
|
|
|
|
Eventually, we would like to write Swift modules which define pure-C entry
|
|
points for top-level functions, and be able to export more data types to
|
|
C code.
|
|
|
|
This will be important for the Linux port, but also perhaps for system
|
|
frameworks that want to transition to Swift.
|
|
|
|
The radars tracking this work are:
|
|
|
|
- rdar://22488618 - @c top-level functions
|
|
- rdar://22490914 - @c structs
|
|
|
|
The new @c attribute
|
|
====================
|
|
|
|
This attribute can be applied to the following kinds of declarations:
|
|
|
|
- top-level functions
|
|
- static methods in non-generic classes
|
|
- enums
|
|
- structs
|
|
|
|
There are two forms of the attribute::
|
|
|
|
@c
|
|
@c(asmname)
|
|
|
|
The latter allows the exported name to be set. By default, the exported
|
|
name is the unmangled, unqualified name of the function or nominal type.
|
|
|
|
There is the question of how to gracefully handle name conflicts inside
|
|
a module. Since C does not have real modules or qualified names, we
|
|
probably can't catch name conflicts until link time. At the very least,
|
|
we will prohibit overloading ``@c`` functions (unless we use Clang-style
|
|
mangling and ``__attribute__((overloadable))``).
|
|
|
|
However, we might want to prefix the default @asmname of a @c symbol
|
|
with the Swift module name followed by an underscore, instead of using
|
|
the unqualified name.
|
|
|
|
Type bridging
|
|
=============
|
|
|
|
The rules for bridging types in ``@c`` function signatures are a subset
|
|
of ``@objc``.
|
|
|
|
Bridgeable types are now partitioned into two broad categories, "POD"
|
|
and "non-POD". POD types include:
|
|
|
|
- integers
|
|
- floating point numbers
|
|
- @c enums
|
|
- fixed size arrays (currently presented as homogeneous tuples of POD types)
|
|
- @c structs (whose fields must all be POD types)
|
|
- pointers to C types
|
|
- @convention(c) function types
|
|
|
|
On Linux, we can't have reference counted pointers here at all, and
|
|
NSArray, etc do not exist, so only POD types are bridgeable. We must
|
|
ensure that we produce the right diagnostic and not crash when the
|
|
user references NSArray, etc on Linux.
|
|
|
|
On Darwin, we can allow passing reference counted pointers directly
|
|
as function parameters. They are still not allowed as fields in ``@c``
|
|
structs, though.
|
|
|
|
The convention for arguments and results can be the same as CoreFoundation
|
|
functions imported from C. The code in ``CFunctionConventions`` in
|
|
SILFunctionType.cpp looks relevant.
|
|
|
|
Bridging header output
|
|
======================
|
|
|
|
We can reuse most of ``PrintAsObjC`` to allow generating pure-C headers
|
|
for Swift modules which use @c but not @objc.
|
|
|
|
Exporting functions to C
|
|
========================
|
|
|
|
Applying ``@c`` to a function is like a combination of ``@convention(c)``
|
|
and ``@asmname(func_name)``.
|
|
|
|
The types in the function signature are bridged as described above, and a
|
|
foreign entry point is generated with the C calling convention and given
|
|
asmname.
|
|
|
|
When the function is referenced from a ``DeclRefExpr`` inside of a
|
|
``FunctionConversionExpr`` to ``@convention(c)``, we emit a direct
|
|
reference to this foreign entry point.
|
|
|
|
@c applied to enums and structs
|
|
===============================
|
|
|
|
For enums, ``@c`` and ``@objc`` can be synonyms. We still have to track
|
|
which one the user used, for accurate printing. On Linux, ``@objc``
|
|
could probably be changed to always diagnose, but this will require
|
|
changing some tests.
|
|
|
|
As stated above, all the fields of a ``@c`` struct must themselves be POD.
|
|
|
|
Structs declared as ``@c`` need to be laid out with C size and alignment
|
|
conventions. We already do that for Swift structs imported from Clang by
|
|
asking Clang to do the layout on Clang AST, so perhaps for ``@c`` structs
|
|
declared in Swift, we can go in the other direction by constructing Clang
|
|
AST for the struct.
|
|
|
|
Accessibility and linkage for @c declarations
|
|
=============================================
|
|
|
|
Only public enums and structs should appear in generated headers; for
|
|
private types, ``@c`` only affects layout and restrictions on the field
|
|
types.
|
|
|
|
For functions, it is not clear if private together with ``@c`` is useful,
|
|
but it could be implemented for completeness. We could either give the
|
|
foreign entry point private linkage, or intentionally give it incorrect
|
|
linkage allowing it to be found with ``dlsym()``.
|
|
|
|
inout parameters in @c and @objc functions
|
|
==========================================
|
|
|
|
Right now we don't allow ``inout`` parameters for ``@objc`` methods.
|
|
We could export them as nonnull pointers, using ``__attribute__((nonnull(N)))``
|
|
rather than ``_Nonnull``.
|
|
|
|
If we ever get as far as implementing C++ interoperability, we could also
|
|
export inouts as references rather than pointers.
|
|
|
|
Diagnostics
|
|
===========
|
|
|
|
Right now all diagnostics for type bridging in Sema talk about Objective-C,
|
|
leading to funny phrasing when using invalid types in a ``@convention(c)``
|
|
function, for instance.
|
|
|
|
All diagnostics need to be audited to take the language as a parameter, and
|
|
either say ``cannot be represented in C`` or ``cannot be represented in
|
|
Objective-C``. A Linux user should never see diagnostics talking about
|
|
Objective-C, except maybe if they explicitly mention ``@objc`` in their code.
|
|
|
|
On the plus side, it is okay if we conservatively talk about ``C`` in
|
|
Objective-C diagnostics on Darwin.
|
|
|
|
Cleanups
|
|
========
|
|
|
|
Right now various aspects of the type bridging mapping are duplicated in
|
|
several places:
|
|
|
|
- ASTContext::getBridgedToObjC()
|
|
- TypeChecker::isRepresentableInObjC() (various overloads)
|
|
- include/swift/ClangImporter/BuiltinMappedTypes.def
|
|
- include/swift/SIL/BridgedTypes.def
|
|
- TypeConverter::getLoweredCBridgedType()
|
|
- ClangImporter::VisitObjCObjectPointerType() and other places in ImportType.cpp
|
|
- PrintAsObjC::printIfKnownGenericStruct()
|
|
- PrintAsObjC::printIfKnownTypeName()
|
|
|
|
We should try to consolidate some of this if possible, to make the
|
|
rules more consistent and easier to describe between Darwin and Linux.
|
|
|