Sorting of DeclContext-local protocols and conformances shouldn't ever
be necessary, because the underlying data structures that produce
these lists should be deterministic. Sorting can hide any
non-determinism, so stop doing it and we can address the underlying
nondeterminism.
The layouts of resilient value types shipped in the Swift 5 standard library
x and overlays will forever be frozen in time for backward deployment to old
Objective-C runtimes. This PR ensures that even if the layouts of these types
evolve in the future, binaries built to run on the old runtime will continue
to lay out class instances in a manner compatible with Swift 5.
Fixes <rdar://problem/45646886>.
This patch prevents writing ivar field for ObjC property whose type
is not trivially representable in ObjC within its DeclContext.
For example, in the case of the property `@objc var foo: String`,
it is accessed as an NSString on the ObjC side. Without this patch,
this property is backed with an ivar, to which direct accesses would
fail.
Resolves: SR-9557.
These are only used in two places in the Apple Objective-C runtime:
- A protocol's "extended method types" list
- Block type descriptors
We were using them when dynamically registering a protocol with the
Objective-C runtime, but that's just expecting "normal" types; the
"extended method types" list is never present in such a protocol.
The metadata reference to the pre-exsting VWT cannot be supported on PE/COFF
due to the direct reference to a value in an external module that is in
static data (the model requires indirecting through memory). Always
force the lazy initialization for the metadata on such platforms.
This requires a secondary change - to initialize the VWT as well. This
is ideally moved into the runtime where we can do this uniformly.
Even if we have a constant value, we might be emitting a legacy layout
that can be updated in place by newer runtimes. In this case, clients
cannot assume the field offsets are constant, and the globals cannot
be constant either.
Part of <rdar://problem/17528739>.
The YAML format is the same one produced by the -dump-type-info
frontend mode.
For now this is only enabled if the -read-type-info-path frontend
flag is specified.
Progress on <rdar://problem/17528739>.
If a class has a backward deployment layout:
- We still want to emit it using the FixedClassMetadataBuilder.
- We still want it to appear in the objc_classes section, and get an
OBJC_CLASS_$_ symbol if its @objc.
- However, we want to use the singleton metadata initialization pattern
in the metadata accessor.
- We want to emit metadata for all field types, and call the
swift_updateClassMetadata() function to initialize the class
metadata.
For now, this function just performs the idempotent initialization of
invoking a static method on the class, causing it to be realized with
the Objective-C runtime.
This silences the instances of the warning from Visual Studio about not all
codepaths returning a value. This makes the output more readable and less
likely to lose useful warnings. NFC.
- 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.
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.
Use the fragile layout to emit static metadata, and use the
resilient metadata for almost everything else.
Add some tests to ensure that we use runtime metadata, even
for classes with fully fragile layout.
We also use this for field offset globals, which are not always
constant. I think in practice everything was getting set
correctly, but it was hard to follow the logic.
We cannot use field offset globals if *any* field of a generic class
with Objective-C ancestry is dependent.
This is because the Swift runtime first performs layout starting
from a static instance start offset, and then asks the Objective-C
runtime to slide the offsets based on the dynamic superclass size.
So if the class has a field of generic type, the alignment of that
type can change the offsets of fields *before* it as well as after.
So we cannot assuem that any fields in such a class have the same
offset across instantiations at all.
The previous fix captured the intent of the above, but it only
kicked in if the immediate superclass of the class was imported
from Objective-C. But really we need to do this for any class with
Objective-C ancestry.
While fixing this, re-organize the code in ClassLayoutBuilder a
little bit to untangle the stored property iteration from the
interesting FieldAccess adjustments that take place after.
Previously we would recursively get the abstract layout for the fully
generic class type for every superclass. But really we only need to do
that for fields of the class itself, not any superclass fields, since
we throw out the superclass field information anyway.
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.
Even if two types are different, they might still have the same
type info, so don't call getLayout() without checking the type info
for identity first. This allows simplifying an early exit into an
assertion elsewhere.
TypeBase::usesNativeReferenceCounting() was doing a lot of work to
find the class that a type refers to, then determine whether it
would use the native reference-counting scheme. Its primary caller
in IRGen would use an overly-conservative approximation to decide
between the “Objective-C” and “unknown” cases, which resulted in
uses of “unknown” reference counting for some obviously-ObjC cases
(e.g., values of “NSObject”).
Moreover, the approximation would try to call into the type checker
(because it relied unnecessarily on the superclass *type* of a class
declaration), causing an assertion.
Fixes rdar://problem/42828798.
Asking isFixedLayout() on the class's StructLayout does not take
missing members or Objective-C sliding into account. Adding a new
bit that carries this information allows removing the hack where
across modules the size of a class was always loaded from metadata.
In practice we hope most classes will be resilient, but its
better to centralize the checking for what resilience means instead
of using different rules in different places.
While most class field accesses go through accessors, a special
case is if you have a final field (or class) in a non-resilient
module. Then, we were allowed to directly access the field.
However, an earlier hack made it so that this access always went
through a field offset global, which is unnecessary in the case
where the class layout is fully known.
One consequence of this is that 'Array.count' would compile down
to a load from a global followed by an indirect load, instead of
a single load from a constant offset.
ClassDecl::getSuperclass() produces a complete interface type describing the
superclass of a class, including any generic arguments (for a generic type).
Most callers only need the referenced ClassDecl, which is (now) cheaper
to compute: switch those callers over to ClassDecl::getSuperclassDecl().
Fixes an existing test for SR-5993.
Switch a number of callers of the Type-based lookupQualified() over to
the newer (and preferred) declaration-based lookupQualified(). These are
the easy ones; NFC.
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