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.
Emit and resolve idValue of KeyPath as an absolute pointer if relative
function pointer is turned-off on Wasm target.
The existing ABI can't distinguish an idValue between function pointer
or data pointer in use-site at compile-time and also at runtime. So this
patch adds a new id resolution scheme `ResolvedAbsolute` to distinguish
them at runtime properly.
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.
The vast majority of generic parameters follow a simple pattern
(type parameter that defines a key argument), which we can take
advantage of to avoid actually representing them in type metadata:
if all the type arguments is the simple pattern, and there's not
more than some preset number, simply use a pre-allocated array in
the runtime.
Actually doing this for generic types will require some care around
back-deployment, as well as finding a bit to store that we've done
it. But we can at least start doing this for new ABI, such as the
extended existential shape descriptors.
Generated code has never actually initialized this field, so we
might as well remove it. Doing so mostly doesn't impact the ABI
since we don't store anything for arguments or results in the
context as part of the normal call sequence. We do need to adjust
some of the hard-coded contexts, however, such as continuation
contexts and the statically-sized context for special runtime
async functions.
Add a few includes of Optional.h and Hashing.h. These files are failing
ot build in the "next" branch due to changes in llvm's own includes, but
it's general goodness to include them on main as well.
A task can be in one of 4 states over its lifetime:
(a) suspended
(b) enqueued
(c) running
(d) completed
This change provides priority inversion avoidance support if a task gets
escalated when it is in state (a), (c), (d).
Radar-Id: rdar://problem/76127624
thread has the task status record lock.
Today, if a thread is holding the StatusRecordLock, then no other
modification of the task status is possible - including a thread
starting to execute the task or stopping execution of the task.
However, the TaskStatusRecordLock is really about protecting the linked
list that is maintained in the ActiveTaskStatus. As such, other
operations which don't need to look at that linked list of us records
really shouldn't have to block on the StatusRecordLock.
This change allows for concurrent modification of the veTaskStatus while
the TaskStatusRecordLock is held. In particular, a task can cancelled,
escalated, start and stop running, all while another ad is holding onto
the task's StatusRecordLock. In the event of cancellation and
escalation, the task's StatusRecordLock must be n in order to propagate
cancellation and escalation to its child tasks is not needed to cancel
or escalate the task itself.
Radar-Id: rdar://problem/76127624
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.