We really don’t need ‘em; we can just adjust the direct field offsets.
The runtime entry point currently uses a weird little hack that we will refactor away shortly.
Rather than having individual methods return without doing anything, arrange for ClassMetadataVisitor to never call them in the first place. This makes it so ClassMetadataScanner also knows which fields are omitted and it can compute offsets correctly.
The old logic is still present for field offsets to make this change NFC.
- VTableSpecializer, a new pass that synthesizes a new vtable per each observed concrete type used
- Don't use full type metadata refs in embedded Swift
- Lazily emit specialized class metadata (LazySpecializedClassMetadata) in IRGen
- Don't emit regular class metadata for a class decl if it's generic (only emit the specialized metadata)
- In embedded Swift, classes get a simplified metadata: Basically just a vtable + destructor + superclass pointer.
- Only non-resilient (intended as permanent restriction), non-generic classes (for now) supported.
- Relax the check that prohibits metadata emission and usage to allow classes.
* [Executors][Distributed] custom executors for distributed actor
* harden ordering guarantees of synthesised fields
* the issue was that a non-default actor must implement the is remote check differently
* NonDefaultDistributedActor to complete support and remote flag handling
* invoke nonDefaultDistributedActorInitialize when necessary in SILGen
* refactor inline assertion into method
* cleanup
* [Executors][Distributed] Update module version for NonDefaultDistributedActor
* Minor docs cleanup
* we solved those fixme's
* add mangling test for non-def-dist-actor
rdar://105837040
* WIP: Store layout string in type metadata
* WIP: More cases working
* WIP: Layout strings almost working
* Add layout string pointer to struct metadata
* Fetch bytecode layout strings from metadata in runtime
* More efficient bytecode layout
* Add support for interpreted generics in layout strings
* Layout string instantiation, take and more
* Remove duplicate information from layout strings
* Include size of previous object in next objects offset to reduce number of increments at runtime
* Add support for existentials
* Build type layout strings with StructBuilder to support target sizes and metadata pointers
* Add support for resilient types
* Properly cache layout strings in compiler
* Generic resilient types working
* Non-generic resilient types working
* Instantiate resilient type in layout when possible
* Fix a few issues around alignment and signing
* Disable generics, fix static alignment
* Fix MultiPayloadEnum size when no extra tag is necessary
* Fixes after rebase
* Cleanup
* Fix most tests
* Fix objcImplementattion and non-Darwin builds
* Fix BytecodeLayouts on non-Darwin
* Fix Linux build
* Fix sizes in linux tests
* Sign layout string pointers
* Use nullptr instead of debug value
That does not work if there is a resilient class in the hiearchy from a
different module than the testable imported one. Rather treat an
internal but testable imported class as having resilient metadata.
The scenario that does not work assuming we can build a fragile layout
is the following.
FrameworkA is resilient and defines a public class `Base` with a stored field.
FrameworkB is resilient and defines an internal class `Sub` that inherits from
the class `Base` in FrameworkA and adds some fields. FrameworkB is compiled
with enable-testing.
The test case testable imports FrameworkB and accesses a field in the
internal class `Base` from FrameworkB. The test case only has access to
FrameworkA's public swiftinterface file and therefore does not know
`Base`'s layout. The layout computation for `Sub` cannot take the field
from `Base` into account and things fail silently.
rdar://103323275
Enable testing makes `internal` types visible from outside the module.
We can no longer treat super classes as resilient.
Follow-up to #41044.
rdar://90489618
Since these types have an implicit stored property, this requires
adding an abstraction over fields to IRGen, at least throughout
the class code. In some ways I think this significantly improves
the code, especially in how we approach missing members.
Fixes rdar://72202671.
A formally virtual method still needs to provide the ABI of an overridable
method, including a dispatch thunk, method descriptor, and support in the
method lookup function for the class to handle `super.` calls from clients.
Fixes a ubsan error on the lldb bots
runtime error: member call on null pointer of type 'swift::SILVTable'
undefined-behavior lib/IRGen/GenMeta.cpp:5107:24
Private and internal classes shouldn't have ABI constraints on their concrete vtable layout, so if methods
don't have overrides in practice, we can elide their vtable entries.
Previously, the various generic builders implemented the methods
addGenericArgument and addGenericWitnessTable without being provided
what argument or witness table they were to add (because it was not
previously needed). Now, the GenericRequirement is passed along to both
methods.
We want to be able to define classes with a fixed storage layout,
but a resilient (opaque) vtable. If the class is also generic,
we still have to load field offsets from the metadata if they
are dependent.
So put the field offsets after the generic arguments and before
the vtable.
This is an ABI break for @_fixed_layout classes, which are
defined by the stdlib.
If the class is resilient to us, we cannot assume anything about the
layout of its member area, so let's not even try; just skip visiting
the members entirely.
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.
Change the "metadata base offset" variable into a "class metadata bounds"
variable that contains the base offset and the +/- bounds on the class.
Link this variable from the class descriptor when the class has a resilient
superclass; otherwise, store the +/- bounds there. Use this variable to
compute the immediate-members offset for various runtime queries. Teach the
runtime to fill it in lazily and remove the code to compute it from the
generated code for instantiation. Identify generic arguments with the start
of the immediate class metadata members / end of the {struct,enum} metadata
header and remove the generic-arguments offset from generic type descriptors.
We would miscompile in mixed-language-version projects when a Swift class was compiled for one language version, while using Objective-C-imported types that are only available to that version, and then imported into a Swift module with a different language version that wasn't able to see all of the properties because of incompatible imported types. This manifested in a number of ways:
- We assumed we could re-derive the constant field offsets of the class's ivars from the layout, which is wrong if properties are missing, causing accesses to final properties or subclass properties to go to the wrong offsets.
- We assumed we could re-derive the instance size and alignment of a class instance in total, causing code to allocate the wrong amount of memory.
- We neglected to account for the space that stored properties take up in the field offset vector of the class object, causing us to load vtable entries for following subclass methods from the wrong offsets.
Eventually, resilience should reduce our exposure to these kinds of problems. As an incremental step in the right direction, when we look at a class from another module in IRGen, treat it as always variably-sized, so we don't try to hardcode offsets, size, or alignment of its instances. When we import a class, and we're unable to import a stored property, leave behind a new kind of MissingMemberDecl that records the number of field offset vector slots it will take up, so that we lay out subclass objects and compute vtable offsets correctly. Fixes rdar://problem/35330067.
A side effect of this is that the RemoteAST library is no longer able to provide fixed field offsets for class ivars. This doesn't appear to impact the lldb test suite, and they will ultimately need to use more abstract access patterns to get ivar offsets from resilient classes (if they aren't already), so I just removed the RemoteAST test cases that tested for class field offsets for now.
We no longer need this for anything, so remove it from metadata
altogether. This simplifies logic for emitting type metadata and
makes type metadata smaller.
We still pass the parent metadata pointer to type constructors;
removing that is a separate change.