Most of this patch is just removing special cases for materializeForSet
or other fairly mechanical replacements. Unfortunately, the rest is
still a fairly big change, and not one that can be easily split apart
because of the quite reasonable reliance on metaprogramming throughout
the compiler. And, of course, there are a bunch of test updates that
have to be sync'ed with the actual change to code-generation.
This is SR-7134.
Previously we would emit class metadata for classes with resilient
ancestry, and relocate it at runtime once the correct size was known.
However most of the fields were blank, so it makes more sense to
construct the metadata from scratch, and store the few bits that we
do need in a true-const pattern where we can use relative pointers.
They were, already, but remove the isConstant parameter to
getAddrOfTypeMetadataPattern(), and just assert that its true for
patterns in defineTypeMetadata() instead.
Also, metadata patterns are i8*, not i8**. In fact they don't contain any
absolute pointers at all.
Should be NFC other than the LLVM type change.
It's confusing to have the generic and concrete type metadata
builders share a common base class, when most of the base class
is not used for the generic case.
Similar to the non-resilient case, except we also emit a 'relocation
function'. The class descriptor now contains this relocation function
if the class has resilient ancestry, and the relocation function
calls the runtime's swift_relocateClassMetadata() entry point.
The metadata completion function calls swift_initClassMetadata() and
does layout, just like the non-resilient case.
Fixes <rdar://problem/40810002>.
Now that we don't need the superclass before calling
swift_relocateClassMetadata(), it seems simpler to set it
here instead of doing it in various places in IRGen.
Using the superclass metadata here no longer makes sense with two-phase
init, in case the superclass metadata depends on the class being
instantiated.
It would also be nice to rework the resilient class metadata 'pattern'
to be its own data structure that's true const, instead of just the
prefix of a real class metadata, but for now let's keep the existing
crappy design.
If a class has generic ancestry or resiliently-sized fields, but is
itself not generic and does not have resilient ancestry, we must
perform runtime metadata initialization, but we can initialize
the metadata in-place.
As with generic classes or classes with resilient ancestry, we
copy generic requirements and field offset vectors from the
superclass. We also calculate the layout of the class's direct
fields at runtime.
Unlike the fully resilient case, we don't copy vtable entries
from the superclass, or install the direct class's vtable
entries from the type context descriptor. Instead, we statically
emit the vtable as with fixed-size class metadata.
Both the in-place and resilient case call the same runtime
entry point to initialize class metadata; the new HasStaticVTable
flag in ClassLayoutFlags is used to select between the two
behaviors concerning the vtable.
- doesClassMetadataRequireRelocation() -- returns true if we must
allocate new metadata at runtime and fill it in, because the class
has multiple instantiations (generic case) or because the total size
of the metadata is not known at compile time (resilient ancestry).
- doesClassMetadataRequireInitialization() -- weaker condition than
the above. It's true if the metadata must be relocated, but it is
also true if the metadata has otherwise fixed size but must be
filled in dynamically. This occurs if the class has generic
ancestry but is itself not generic, or if the class has
resiliently-sized fields, or missing members.
For now, we don't actually care about the distinciton anywhere,
because we cannot do in-place initialization of class metadata yet.
- getAsDeclOrDeclExtensionContext -> getAsDecl
This is basically the same as a dyn_cast, so it should use a 'getAs'
name like TypeBase does.
- getAsNominalTypeOrNominalTypeExtensionContext -> getSelfNominalTypeDecl
- getAsClassOrClassExtensionContext -> getSelfClassDecl
- getAsEnumOrEnumExtensionContext -> getSelfEnumDecl
- getAsStructOrStructExtensionContext -> getSelfStructDecl
- getAsProtocolOrProtocolExtensionContext -> getSelfProtocolDecl
- getAsTypeOrTypeExtensionContext -> getSelfTypeDecl (private)
These do /not/ return some form of 'this'; instead, they get the
extended types when 'this' is an extension. They started off life with
'is' names, which makes sense, but changed to this at some point. The
names I went with match up with getSelfInterfaceType and
getSelfTypeInContext, even though strictly speaking they're closer to
what getDeclaredInterfaceType does. But it didn't seem right to claim
that an extension "declares" the ClassDecl here.
- getAsProtocolExtensionContext -> getExtendedProtocolDecl
Like the above, this didn't return the ExtensionDecl; it returned its
extended type.
This entire commit is a mechanical change: find-and-replace, followed
by manual reformatted but no code changes.
This saves us some expensive cross-referencing and caching in the runtime, and lets us reclaim the `isReflectable` bit from the context descriptor flags (since a null field descriptor is a suitable and more accurate indicator of whether a type is reflectable).
Certain uses of protocols only formally need the requirement
signature, not any of the method requirements. This results in IRGen
seeing a protocol where none of the members have been validated except
the associated types. Account for this by allowing ProtocolInfo to
only contain the layout for the base protocols and associated types,
if requested.
Note that this relies on the layout of a witness table always putting
the "requirement signature part" at the front, or at least at offsets
that aren't affected by function requirements.
rdar://problem/43260117
We’re not using this parameter, and don’t expect to do so in the future,
so remove it. Also fold away TypeBase::usesNativeReferenceCounting()
and irgen::getReferenceCountingForType(), both of which are trivial.
We don't need to substitute the superclass type as we walk up a
class hierarchy, or look up the generic parameters and conformances
to check if they're concrete, since we're always just emitting
null pointers in place of the generic parameters and requirements,
to be filled at runtime.
Also, don't leave space for generic parameters and requirements from
Objective-C superclasses, since that's not how they're represented.
The type info for a class described its layout using a combination of a
StructLayout and ClassLayout, with different information stored in both.
Since we never use a class as a struct, it's simpler to add the relevant
bits to ClassLayout, and not build a StructLayout at all.
Also, drop inherited properties from the ClassLayout -- they're no
longer needed.
When emitting fixed class metadata, we emit field offsets for all fields,
including those from superclasses, if any.
Get the ClassLayout for the correct class before looking up a field that
might potentially belong to a superclass. Soon, I'm going to slim down
ClassLayout instances to only store the fields belonging to the class
itself, removing the InheritedStoredProperites array altogether.
- Instead of keeping multiple flags in the type descriptor flags,
just keep a single flag indicating the presence of additional
import information after the name.
- That import information consists of a sequence of null-terminated
C strings, terminated by an empty string (i.e. by a double null
terminator), each prefixed with a character describing its purpose.
- In addition to the symbol namespace and related entity name,
include the ABI name if it differs from the user-facing name of the
type, and make the name the user-facing Swift name.
There's a remaining issue here that isn't great: we don't correctly
represent the parent relationship between error types and their codes,
and instead we just use the Clang module as the parent. But I'll
leave that for a later commit.
- `swift_getForeignTypeMetadata` is now a request/response function.
- The initialization function is now a completion function, and the
pointer to it has moved into the type descriptor.
- The cache variable is no longer part of the ABI; it's an
implementation detail of the access function.
- The two points above mean that there is no special header on foreign
type metadata and therefore that they can be marked constant when
there isn't something about them that needs to be initialized.
The only foreign-metadata initialization we actually do right now is
of the superclass field of a foreign class, and since that relationship
is a proper DAG, it's not actually possible to have recursive
initialization problems. But this is the right long-term thing to do,
and it removes one of the last two clients of once-based initialization.
As part of this, rename TypeMetadataRecordKind to TypeReferenceKind
and consistently give it three bits of storage.
The better modelling of these type references appears to have been
sufficient to make dynamic conformance checks succeed, which is good
but unexpected.
The central thrust of this patch is to get these metadata initializations
off of `swift_once` and onto the metadata-request system where we can
properly detect and resolve dependencies. We do this by first introducing
runtime support for resolving metadata requests for "in-place"
initializations (committed previously) and then teaching IRGen to actually
generate code to use them (this patch).
A non-trivial amount of this patch is just renaming and refactoring some of
existing infrastructure that was being used for in-place initializations to
try to avoid unnecessary confusion.
The remaining cases that are still using `swift_once` resolution of
metadata initialization are:
- non-generic classes that can't statically fill their superclass or
have resilient internal layout
- foreign type metadata
Classes require more work because I'd like to switch at least the
resilient-superclass case over to using a pattern much more like what
we do with generic class instantiation. That is, I'd like in-place
initialization to be reserved for classes that actually don't need
relocation.
Foreign metadata should also be updated to the request/dependency scheme
before we declare ABI stability. I'm not sure why foreign metadata
would ever require a type to be resolved, but let's assume it's possible.
Fixes part of SR-7876.
Rather than storing a mangled name in a Swift protocol descriptor,
which encodes information that is redundant with the context of the
protocol, store an unmangled name as in nominal type descriptors. Update
the various places where this name is used to extract the demangle
tree from the context descriptors.
Reimplement protocol descriptors for Swift protocols as a kind of
context descriptor, dropping the Objective-C protocol compatibility
layout. The new protocol descriptors have several advantages over the
current implementation:
* They drop all of the unused fields required for layout-compatibility
with Objective-C protocols.
* They encode the full requirement signature of the protocol. This
maintains more information about the protocol itself, including
(e.g.) correctly encoding superclass requirements.
* They fit within the general scheme of context descriptors, rather than
being their own thing, which allows us to share more code with
nominal type descriptors.
* They only use relative pointers, so they’re smaller and can be placed
in read-only memory
Implements rdar://problem/38815359.
For now, the accessors have been underscored as `_read` and `_modify`.
I'll prepare an evolution proposal for this feature which should allow
us to remove the underscores or, y'know, rename them to `purple` and
`lettuce`.
`_read` accessors do not make any effort yet to avoid copying the
value being yielded. I'll work on it in follow-up patches.
Opaque accesses to properties and subscripts defined with `_modify`
accessors will use an inefficient `materializeForSet` pattern that
materializes the value to a temporary instead of accessing it in-place.
That will be fixed by migrating to `modify` over `materializeForSet`,
which is next up after the `read` optimizations.
SIL ownership verification doesn't pass yet for the test cases here
because of a general fault in SILGen where borrows can outlive their
borrowed value due to being cleaned up on the general cleanup stack
when the borrowed value is cleaned up on the formal-access stack.
Michael, Andy, and I discussed various ways to fix this, but it seems
clear to me that it's not in any way specific to coroutine accesses.
rdar://35399664
In a generic requirement, distinguish between Swift and
Objective-C protocols using a spare bit within the relative
(indirectable) reference to the protocol.