Swift-defined @objc protocols are registered with the Objective-C runtime
under the Swift 3 mangling scheme; look in the Objective-C runting using
objc_getProtocol() with the appropriate name.
Also, correctly compute the "class bound" bit when forming a protocol
composition metatype. The information isn't in the mangled name when it
can be recovered from the protocols themselves, so look at the protocols.
Search through the new section containing Swift protocol descriptor
references to resolve protocols by mangled name. Use this
functionality to support protocol composition types within
_typeForMangledName.
This makes them consistent no matter what shenanigans are pulled by
the importer, particularly NS_ENUM vs. NS_OPTIONS and NS_SWIFT_NAME.
The 'NSErrorDomain' API note /nearly/ works with this, but the
synthesized error struct is still mangled as a Swift declaration,
which means it's not rename-stable. See follow-up commits.
The main place where this still falls down is NS_STRING_ENUM: when
this is applied, a typedef is imported as a unique struct, but without
it it's just a typealias for the underlying type. There's also still a
problem with synthesized conformances, which have a module mangled
into the witness table symbol even though that symbol is linkonce_odr.
rdar://problem/31616162
Introduce a new section that contains (relative) references to all of the
Swift protocol descriptors emitted into this module. We'll use this to
find protocol descriptors by name.
TypeDecoder's interface with its builders already treated protocols as
a type (due to their being mangled as "protocol composition containing
one type"), and intermixed protocols with superclasses when forming
compositions. This makes for some awkwardness when working with
protocol descriptors, which are very much a distinct entity from a
type.
Separate out the notion of a "protocol declaration" (now represented
by the builder-provided BuiltProtocolDecl type) from "a protocol
composition containing a single type", similarly to the way we handle
nominal type declarations. Teach remote mirrors and remote AST to
handle the new contract.
The mangled name of protocol descriptors was the “protocol composition”
type consisting of a single protocol, which is a little odd. Instead,
use a bare protocol reference (e.g., “6Module5ProtoP”) with the “$S”
prefer to be more in line with nominal type descriptor names while still
making it clear that this is a Swift (not an Objective-C) protocol.
If the value was wrapped in an existential buffer, we would never
release the original value even though it was passed in at +1.
Fixes <rdar://problem/36153982>, <https://bugs.swift.org/browse/SR-6536>.
_getTypeByMangledName() is more general and will be the way forward. Use
that instead. Note that we're still keeping around Foundation-only SPI
function _typeByName() in the Swift standard library, until we settle
on what the standard library API should be like for this functionality.
Now that all nominal types have nominal type descriptors, directly
search for nominal type descriptors when looking up metadata by
mangled name. This eliminates some bouncing between metadata and
nominal type descriptor when decoding a mangled name.
Introduce a flags parameter to swift_getTupleTypeMetadata(). Add a flag
stating when the "labels" parameter points into nonconstant memory, in
which case we need to make a copy of the string before adding an entry
into the concurrent map.
Introduce a standard library/runtime entry point that produces type metadata
given a mangled name, based on the TypeDecoder logic lifted from the remote
mirrors library.
Implement support for tuple types as a proof-of-concept.
Since it's not very common to use such ABI endpoints, let's remove
them and use the most general one `swift_getFunctionTypeMetadata`
instead when function parameters have flags attached to them.
Resolves: rdar://problem/36278686
This ABI endpoint is used to retrieve metadata about functions
without parameters. Which is very common use-case and it
makes sense to save some code size for that.
Now that we use nominal type descriptors for everything that we can within
protocol conformance records, eliminate the unused
"NonuniqueDirectType" case and all of the code that supports it. Leave
this value explicitly reserved for the future.
Nominal type descriptors are not always unique, so testing them via pointer
equality is not correct. Introduce an "isEqual()" operation for
nominal type descriptors that performs the appropriate equality check,
using pointer equality when possible, and falling back to string
comparisons of the mangled type name when it is not possible.
Introduce a "nonunique" flag into nominal type descriptors to describe
when they are, in fact, not unique. The only nonunique nominal type
descriptors currently come from Clang-imported types; all
Swift-defined types have unique nominal type descriptors. Use this
flag to make the aforementioned operation efficient in the "unique"
case.
Use the new isEqual() operation for protocol conformance lookup, and
make sure we're caching results based on the known-canonical nominal
type descriptor.
The separate section of type references uses the same type reference format
as in protocol conformance records. As with protocol conformance records,
mangle the type reference kind into the lower two bits. Then, eliminate the
separate "flags" field from the type metadata record. Finally, rename
the section because the Swift 5 stable format for this section is
different from prior formats, and the two runtimes need to be able to
coexist.
Use the spare bits within the type reference field to describe the kinds
of type metadata records, so that we no longer need to rely on a
separate "flags" field.
Rather than emitting unique, direct type metadata for non-foreign
types, emit a reference to the nominal type descriptor. This collapses
the set of type metadata reference kinds to 3: nominal type
descriptor, (indirect) Objective-C class object, and nonuniqued
foreign type metadata.
If the nominal type descriptor's resilient superclass flag
is set, the generic parameter offset, vtable start offset
and field offset start offset are all relative to the
start of the class's immedaite members, and not the start
of the class metadata.
Support this by loading the size of the superclass and
adding it to these offsets if the flag is set.
Now that references to Objective-C class objects are indirected
(via UniqueIndirectClass), classes with Swift type metadata can be
directly referenced (via UniqueDirectType) rather than hopping through
swift_getObjCClassMetadata().
The format of protocol conformance records will be changing in Swift 5, so
rename the segment (from, e.g., __swift2_proto to __swift5_proto) to allow
Swift < 5 and Swift 5+ runtimes to coexist.
The protocol conformance record has two bits to describe how the
witness table will be produced. There are currently three states
(direct reference to witness table, witness table accessor, and
conditional witness table accessor). Add a reserved case for the
fourth state so the Swift 5 runtime will (silently) ignore
conformances using that fourth state, when/if some future Swift
uses it.
Swift class metadata has a bit to distinguish it from non-Swift Objective-C
classes. The stable ABI will use a different bit so that stable Swift and
pre-stable Swift can be distinguished from each other.
No bits are actually changed yet. Enabling the new bit needs to wait for
other coordination such as libobjc.
rdar://35767811
- Create the value witness table as a separate global object instead
of concatenating it to the metadata pattern.
- Always pass the metadata to the runtime and let the runtime handle
instantiating or modifying the value witness table.
- Pass the right layout algorithm version to the runtime; currently
this is always "Swift 5".
- Create a runtime function to instantiate single-case enums.
Among other things, this makes the copying of the VWT, and any
modifications of it, explicit and in the runtime, which is more
future-proof.
We can reduce the uniquing header from 3–4 pointer-sized words down to 1–2 32-bit words + one pointer:
- The initialization function (when present) and name are always emitted into the same binary image, so we can use relative references to shrink these down to 32-bit fields.
- We don't ever simultaneously need the initialization flags and the initialized uniqued pointer. (Keeping the "initialization function" flag bit theoretically lets us turn a "consume" load into a "relaxed" load, but that makes no practical difference on most contemporary architectures.) 12 flag bits Ought To Be Enough For Anyone and lets us reliably tell a valid pointer from a flag set, so overlap the initialization flags with the eventual invasive cache value.
The invasive cache is left inline, since we've decided we're not going to make the rest of type metadata records ever be true-const, so they'll already be sitting on a dirty page. A dynamic linker that was sufficiently Swift-optimized to precalculate the other load-time-initialized entries in metadata could likely precompute the invasive cache value as well.
rdar://problem/22527141