Two protocol conformance descriptors are passed to
swift_compareProtocolConformanceDecriptors from generic metadata
accessors when there is a canonical prespecialization and one of the
generic arguments has a protocol requirement.
Previously, the descriptors were incorrectly being passed without
ptrauth processing: one from the witness table in the arguments that are
passed in to the accessor and one known statically.
Here, the descriptor in the witness table is authed using the
ProtocolConformanceDescriptor schema. Then, both descriptors are signed
using the ProtocolConformanceDescriptorsAsArguments schema. Finally, in
the runtime function, the descriptors are authed.
Previously, the metadata accessor for a generic type for which some
metadata prespecialization was done only tested that the type metadata
arguments were equal to those of the prespecialization. If the generic
type had an argument which was constrained to conform to a protocol, the
particular conformance to that protocol was determined at compile time,
but the conformance was ignored in the metadata accessor. As a result
it was possible--in certain multi-module cases--for the metadata
accessor to incorrectly return a prespecialized metadata record whose
type arguments matched the type arguments passed to the accessor but
whose conformance arguments did not.
For example, given the following,
Base:
struct K {}
protocol P {}
Conformance1:
import Base
struct G<T : P> {}
extension K : P {} // first conformance
prespecialize( G<K>.self )
Conformance2:
import Base
extension K : P {} // second conformance
the metadata accessor for G defined in Conformance1 would behave like
MetadataResponse `metadata accessor for G`(
MetadataRequest request,
const Metadata *M,
const WitnessTable *WT) {
if (M == `type metadata for K`) {
return `canonical prespecialized type metadata for G<K>`
}
return swift_getGenericMetadata(request, {M, WT});
}
Here, the WitnessTable argument is the witness table describing a
conformance of the type whose metadata is provided to the protocol P.
The incorrect behavior occurs when calling the metadata accessor with
these arguments:
`some request`
`type metadata for K`
`protocol witness table for Base.K : Base.P in Conformance2`
The accessor would return the `canonical prespecialized type metadata
for G<K>`. The problem is that the prespecialized metadata contains the
following generic arguments:
`type metadata for K`
`protocol witness table for Base.K : Base.P in Conformance1`
Specificallly, the witness table is for the conformance from
Conformance1, not the conformance from Conformance2.
Here, the problem is addressed by testing that the witness tables passed
into the accessor are for the same conformance as the witness table
referred to by the prespecialized record. Now, the metadata accessor
for G will behave like
MetadataResponse `metadata accessor for G`(
MetadataRequest request,
const Metadata *M,
const WitnessTable *WT) {
if (M == `type metadata for K`
swift_compareProtocolConformanceDescriptors(
WT->getDescription(),
`protocol conformance descriptor for Base.K : Base.P in Conformance1`)
) {
return `canonical prespecialized type metadata for G<K>`
}
return swift_getGenericMetadata(request, {M, WT});
}
Consequently, when the accessor is called with the same arguments as
before, the call to swift_compareProtocolConformanceDescriptors will
return false and the non-matching prespecialized metadata will not be
returned.
Previously, metadata prespecialization for classes only occurred when
all of a specialized generic class's ancestors were themselves generic.
Here, that requirement is lifted so that generic classes with concrete
ancestors are also eligible for prespecialization.
Previously a bool argument was passed to
isCanonicalSpecializedNominalTypeMetadataStaticallyAddressable to
indicate whether the metadata was to be used only from a specialized
metadata accessor. Here, that bool is replaced with an enum.
When generic metadata for a class is requested in the same module where
the class is defined, rather than a call to the generic metadata
accessor or to a variant of typeForMangledNode, a call to a new
accessor--a canonical specialized generic metadata accessor--is emitted.
The new function is defined schematically as follows:
MetadataResponse `canonical specialized metadata accessor for C<K>`(MetadataRequest request) {
(void)`canonical specialized metadata accessor for superclass(C<K>)`(::Complete)
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, 1)`(::Complete)
...
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, count)`(::Complete)
auto *metadata = objc_opt_self(`canonical specialized metadata for C<K>`);
return {metadata, MetadataState::Complete};
}
where generic_argument_class(C<K>, N) denotes the Nth generic argument
which is both (1) itself a specialized generic type and is also (2) a
class. These calls to the specialized metadata accessors for these
related types ensure that all generic class types are registered with
the Objective-C runtime.
To enable these new canonical specialized generic metadata accessors,
metadata for generic classes is prespecialized as needed. So are the
metaclasses and the corresponding rodata.
Previously, the lazy objc naming hook was registered during process
execution when the first generic class metadata was instantiated. Since
that instantiation may occur "before process launch" (i.e. if the
generic metadata is prespecialized), the lazy naming hook is now
installed at process launch.
Clang provides options to override that default value.
These options are accessible via the -Xcc flag.
Some Swift functions explicitly disable the frame pointer.
The clang options will not override those.
Previously, prespecialization was incorrectly being performed for
non-resilient types defined by other modules. This is incorrect for
statically canonical metadata records because in order to be canonical,
they need to be returned from the metadata accessor which is emitted by
the module which defines the type.
Without whole module optimization, the metadata accessors are emitted on
a per-file basis. The result is that if the file containing a generic
type is processed before the file containing a usage of that type that
would result in that prespecialization, the metadata accessor would have
already been emitted by the time that the usage is noted, making it
impossible for the newly created prespecialization to be returned from
the already-emitted metadata accessor.
Here, require that either whole module optimization is enabled so that
the metadata accessors are all emitted at once at the end, or else that
the usage of the prespecialization is in the same file as the type is
declared.
Add mangling scheme for `@differentiable` and `@differentiable(linear)` function
types. Mangling support is important for debug information, among other things.
Update docs and add tests.
Resolves TF-948.
The only initialization these class objects need is ObjC realization, which can be done
fast with `objc_opt_self` on recent Apple OSes. The cache check just adds code size and
dirties memory.
Some metadata may require instantiation, but not in a way that requires us to put an additional
cache layer in front of it. `Self` metadata is also trivial to access from the local cache, but
isn't statically referenceable. Split these concepts and update code to use one or the other
appropriately. This catches an issue with metadata prespecialization where it would try to
make records for dynamic `Self` incorrectly.
When a specialized usage of a generic enum occurs in the same module
where the enum was defined, directly reference the prespecialized
metadata.
rdar://problem/56994321
To achieve this replace the current implementation which recursively
constructs a layout compatible metadata by an implementation that
recursively constructs a layout compatible type and the use
emitTypeMetadataRef on that type to generate the metadata.
Previously, some ad hoc checks were done in order to determine whether
the metadata access for a generic type was trivial. Now, standard
predicates are used, specifically IRGenModule's member functions
isDependentConformance and isResilientConformance.
Previously, when emitting the metadata accessor, the generic arguments
of the type were enumerated one after the next. That was fine in most
cases but is incorrect in cases where the actual number of generic
arguments is less than apparent number as when two arguments are required
to be equal.
Now, the arguments are enumerated according to the requirements vended by
the GenericTypeRequirements struct.
Recently we started using the runtime demangler to realize imported
Objective-C class metadata, to save on code size since no metadata
accessor function needs to be emitted in this case.
This introduced a regression where OBJC_CLASSREF symbols were no
longer being emitted in some cases, which breaks autolinking.
The fix for this was tracked by rdar://56136123, but unfortunately
had to be reverted because it caused other problems.
Until the original fix can be re-applied, let's put in a temporary
workaround where we avoid going through the runtime demangler for
imported Objective-C classes. This regresses code size but unblocks
everyone involved, until the fix for the demangling code path
(8247525471) can be re-applied.
Fixes <rdar://56621277>.
Metadata accessors are dependent on prespecializations of the metadata
of generic, in-module types. Those prespecializations are themselves
dependent on usages of the types in functions. Consequently, the
accessors must be emitted after all the functions are emitted.
When possible, directly reference metadata prespecializations. Doing so
is possible when the type is defined in the same module, because in
those cases the metadata accessor can be modified to ensure that the
prespecialized metadata is canonical.
rdar://problem/56994171
For every prespecialization of generic metadata that exists in the
module where the generic type is defined, the metadata accessor gains
code with the following effect
switch arguments {
case prespecialization1.genericArguments:
return prespecialization1
case prespecialization2.genericArguments:
return prespecialization2
...
default:
return swift_getGenericMetadata(...)
}
rdar://problem/56961700
When emitting a reference to the metadata for a generic type, prepare
to, rather than always inserting calls to the type metadata access
function, emit direct references to static specializations when possible
and emit calls to the forthcoming swift_getCanonicalSpecializedMetadata
when not possible.
For now, the metadata access function is always called.
use getTypeByMangledName when abstract metadata state is requested
This can significantly reduce the code size of apps constructing deeply
nested types with conditional conformances.
Requires a new runtime.
rdar://57157619