Tidy up the metadata definitions.
* Generalize a number of metadata kinds for out-of-process clients
* Introduce conveniences to make runtime lookups easier
* Introduce TargetExistentialTypeExpression to TrailingObjects stops complaining about OverloadTokens being ambiguous
Note that there is no impact on the layout of the metadata - the changes here are all ABI-compatible.
I wrote out this whole analysis of why different existential types
might have the same logical content, and then I turned around and
immediately uniqued existential shapes purely by logical content
rather than the (generalized) formal type. Oh well. At least it's
not too late to make ABI changes like this.
We now store a reference to a mangling of the generalized formal
type directly in the shape. This type alone is sufficient to unique
the shape:
- By the nature of the generalization algorithm, every type parameter
in the generalization signature should be mentioned in the
generalized formal type in a deterministic order.
- By the nature of the generalization algorithm, every other
requirement in the generalization signature should be implied
by the positions in which generalization type parameters appear
(e.g. because the formal type is C<T> & P, where C constrains
its type parameter for well-formedness).
- The requirement signature and type expression are extracted from
the existential type.
As a result, we no longer rely on computing a unique hash at
compile time.
Storing this separately from the requirement signature potentially
allows runtimes with general shape support to work with future
extensions to existential types even if they cannot demangle the
generalized formal type.
Storing the generalized formal type also allows us to easily and
reliably extract the formal type of the existential. Otherwise,
it's quite a heroic endeavor to match requirements back up with
primary associated types. Doing so would also only allows us to
extract *some* matching formal type, not necessarily the *right*
formal type. So there's some good synergy here.
When SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER is enabled, relative direct
pointers whose pointees are functions will be turned into absolute
pointer at compile-time.
The immediate use case is only concretely-constrained existential
types, which could use a much simpler representation, but I've
future-proofed the representation as much as I can; thus, the
requirement signature can have arbitrary parameters and
requirements, and the type can have an arbitrary type as the
sub-expression. The latter is also necessary for existential
metatypes.
The chief implementation complexity here is that we must be able
to agree on the identity of an existential type that might be
produced by substitution. Thus, for example, `any P<T>` when
`T == Int` must resolve to the same type metadata as
`any P<Int>`. To handle this, we identify the "shape" of the
existential type, consisting of those parts which cannot possibly
be the result of substitution, and then abstract the substitutable
"holes" as an application of a generalization signature. That
algorithm will come in a later patch; this patch just represents
it.
Uniquing existential shapes from the requirements would be quite
complex because of all the symbolic mangled names they use.
This is particularly true because it's not reasonable to require
translation units to agree about what portions they mangle vs.
reference symbolically. Instead, we expect the compiler to do
a cryptographic hash of a mangling of the shape, then use that
as the unique key identifying the shape.
This is just the core representation and runtime interface; other
parts of the runtime, such as dynamic casting and demangling
support, will come later.
Previously, the code assumed that such an indirect target will always point to an external symbol pointer, but it can also be an absolute pointer to an in-image protocol descriptor.
This fixes the build on Windows by fixing the template code. The
template type was not qualified and caused an ambiguity in the name
resolution with the local typename and the previously declared
namespaced name.
In order to be able to debug, for example, a Linux process from a macOS host, we
need to be able to initialize a ReflectionContext without Objective-C
interoperability. This patch turns ObjCInterOp into another template trait, so
it's possible to instantiate a non-ObjC MetadataReader on a system built with
ObjC-interop (but not vice versa).
This patch changes the class hierarchy to
TargetMetadata<Runtime>
|
TargetHeapMetadata<Runtime>
|
TargetAnyClassMetadata<Runtime>
/ \
/ TargetAnyClassMetadataObjCInterop<Runtime>
/ \
TargetClassMetadata<Runtime, TargetAnyClassMetadata<Runtime>> \
\
TargetClassMetadata<Runtime, TargetAnyClassMetadataObjCInterop<Runtime>>
TargetAnyClassMetadataObjCInterop inherits from TargetAnyClassMetadata because
most of the implementation is the same. This choice makes TargetClassMetadata a
bit tricky. In this patch I went with templating the parent class.
rdar://87179578
Direct pointer to the accessor cannot be called at runtime,
so here is how everything is stored:
- For `distributed` and `async` functions -> async function pointer;
- For regular functions -> function pointer.
A "accessible" function that can be looked up based on a string key,
and then called through a fully-abstracted entry point whose arguments
can be constructed in code.
Implement name mangling, type metadata, runtime demangling, etc. for
global-actor qualified function types. Ensure that the manglings
round-trip through the various subsystems.
Implements rdar://78269642.
It seems that MSVC 2017 trips parsing an using of a using of a variadic
template. Removing one level of using seems to work fine. A preprocessor
macro allows to keep using the same syntax in both MSVC 2017 and other
compilers without making a lot of a mess.
I think this might have been uncovered by landing apple/llvm-project#2898
when it was picked up by the auto-merger for the swift/main branch.
I think this was not a problem until now, because Metadata.h was
compiled using the just compiled Clang until now. LLDB is compiled using
MSVC in Windows.
Allow runtime metadata queries to determine if a "class" (in the
runtime) is actually an actor by adding a bit to the class context
descriptor's type-specific kind flags.
Implements rdar://77073762.
* Move differentiability kinds from target function type metadata to trailing objects so that we don't exhaust all remaining bits of function type metadata.
* Differentiability kind is now stored in a tail-allocated word when function type flags say it's differentiable, located immediately after the normal function type metadata's contents (with proper alignment in between).
* Add new runtime function `swift_getFunctionTypeMetadataDifferentiable` which handles differentiable function types.
* Fix mangling of different differentiability kinds in function types. Mangle it like `ConcurrentFunctionType` so that we can drop special cases for escaping functions.
```
function-signature ::= params-type params-type async? sendable? throws? differentiable? // results and parameters
...
differentiable ::= 'jf' // @differentiable(_forward) on function type
differentiable ::= 'jr' // @differentiable(reverse) on function type
differentiable ::= 'jd' // @differentiable on function type
differentiable ::= 'jl' // @differentiable(_linear) on function type
```
Resolves rdar://75240064.
Fill out the metadata for Job to have a Dispatch-compatible vtable. When available, use the dispatch_enqueue_onto_queue_4Swift to enqueue Jobs directly onto queues. Otherwise, keep using dispatch_async_f as we have been.
rdar://75227953
Create a TargetDispatchClassMetadata for Swift metadata that also has a dispatch-compatible vtable. Dispatch leaves room for ObjC class metadata so the two regions don't overlap. (The vtable currently consists of a single dummy entry; this will be filled out later.)
Rearrange the Job and AsyncTask hierarchy so that AsyncTask inherits only from Job, which in turn inherits from HeapObject. This gives all Job instances a dispatch-compatible isa field. It also gives them a refcount word, which is wasted on instances that aren't AsyncTask instances. Maybe we can find some use for that space in the future.
rdar://75227953
Introduce `@concurrent` attribute on function types, including:
* Parsing as a type attribute
* (De-/re-/)mangling for concurrent function types
* Implicit conversion from @concurrent to non-@concurrent
- (De-)serialization for concurrent function types
- AST printing and dumping support
Emit a once token when adding canonical prespecialized metadata records
to a nominal type descriptor and add the token itself as a trailing
object to the type descriptor. The new token will, in subsequent
commits, enable the canonical prespecialized metadata records attached
to the type descriptor to be added to the metadata cache exactly once.
The attachment of the canonical prespecializations to the generic type
will enable runtime functions to look through the canonical
prespecializations in order to return them (getGenericMetadata) and
register them with the runtime (getSpecializedGenericMetadata).
Add `async` to the type system. `async` can be written as part of a
function type or function declaration, following the parameter list, e.g.,
func doSomeWork() async { ... }
`async` functions are distinct from non-`async` functions and there
are no conversions amongst them. At present, `async` functions do not
*do* anything, but this commit fully supports them as a distinct kind
of function throughout:
* Parsing of `async`
* AST representation of `async` in declarations and types
* Syntactic type representation of `async`
* (De-/re-)mangling of function types involving 'async'
* Runtime type representation and reconstruction of function types
involving `async`.
* Dynamic casting restrictions for `async` function types
* (De-)serialization of `async` function types
* Disabling overriding, witness matching, and conversions with
differing `async`
The new function swift_getCanonicalSpecializedMetadata takes a metadata
request, a prespecialized non-canonical metadata, and a cache as its
arguments. The idea of the function is either to bless the provided
prespecialized metadata as canonical if there is not currently a
canonical metadata record for the type it describes or else to return
the actual canonical metadata.
When called, the metadata cache checks for a preexisting entry for this
metadata. If none is found, the passed-in prespecialized metadata is
added to the cache. Otherwise, the metadata record found in the cache
is returned.
rdar://problem/56995359
This simply uses the qualified names for `StringRef` and `Optional` to
help with use of regular expressions to identify the usage to help
migrate the references away from `LLVMSupport` to enable explicitly
vending a custom `LLVMSupport` in the runtime.
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.