Add requirements to the Builder concept to construct generic signatures and substitution maps. Then introduce a `subst` requirement that uses the substitution map to call through to the builder's notion of type (ref) substitution.
This infrastructure is sufficient to model the notion of a RuntimeGenericSignature.
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.
Apply a blanket pass of including `new` for the placement new allocation
and namespacing the call to the global placement new allocator. This
should repair the Android ARMv7 builds.
The android build seems to find a conflict in the overload set for the
placement new operator due to the custom new overload. Provide the
indicator that we want the placement new allocator by using the
explicitly namespaced spelling.
Thanks to @buttaface for reporting the build failure.
The placement new operator is only available when `<new>` has been
included. Add the missing include to the header to allow us to get the
definition of the placement new allocator. This allows us to remove the
workaround that was there for Windows, and should hopefully repair the
Android build as well.
Thanks to @grynspan for helping identify the underlying issue!
Not all targets have a 16-byte type alignment guarantee. For the types
which are not naturally aligned, provide a type specific `operator new`
overload to ensure that we are properly aligning the type on allocation
as we run the risk of under-aligned allocations otherwise.
This should no longer be needed with C++17 and newer which do a two
phase `operator new` lookup preferring
`operator new(std::size, std::align_val_t)` if needed. The base type
would be fully pre-processed away. The empty base class optimization
should help ensure that we do not pay any extra size costs for the
alignment fixes.
As we are a C++14 codebase, we must locally implement some of the
standard type_traits utilities, namely `void_t`. We take the minimal
definition here, assuming that the compiler is up-to-date with C++14 DR
reports which fixed an issue in SFINAE. We use the SFINAE for detecting
the presence of the `operator new` overload to guide the over-alignment,
which is inherited through the new `swift::overaligned_type<>` base
type.
Annotate the known classes which request explicit alignment which is
non-pointer alignment. This list was identified by
`git grep ' alignas(.*) '`.
When SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER is enabled, relative direct
pointers whose pointees are functions will be turned into absolute
pointer at compile-time.
Starting with Android 11, AArch64 placed a tag in the top byte of pointers to
allocations, which has been slowly rolling out to more devices and collides
with Swift's tags. Moving these tags to the second byte works around this
problem.
When storing a tag into a multi-payload enum for an empty case via
swift_storeEnumTagMultiPayload, the tag is split between the storage for
payloads (i.e. the associated values of the non-empty cases) and the
storage for tags (i.e. the integers which refer to the non-empty cases).
Typically, the number of non-empty cases (i.e. one beyond the tag
that refers to the last non-empty case) is stored into the tag storage
and the integer which distinguishes which among the empty cases the enum
is in is stored into storage for payloads. When the enum is small,
however--specifically, when the payload size is less than four
bytes--that information is packaged differently via masking.
Previously, there was a problem with that masking. While the value
stored into the tag storage was correct (and correctly indicated that
the enum was in some empty case), the value stored into the payload
storage was not. The result was that which empty case an enum was in
would be corrupted.
Here, that is fixed by fixing the masking.
rdar://87914343
Moved the _gCRAnnotations declarations to their own object module,
which will help to avoid duplicate symbol problems (at least with .a
files).
Also tweaked things to make it so that the demangler and runtime
versions of the message setting code will interoperate (and so that
they'll interoperate better with other implementations that might
creep in from somewhere, like the one in LLVMSupport).
rdar://91095592
Generating a statically-linked executable either with
`-static-executable` or `-static-stdlib` that contains concurrency needs
to link the concurrency libraries or the missing symbols will cause link
failures.
This patch adds dispatch and blocks runtime to the list of statically
linked libraries. In the case of the static stdlib, it only adds them if
the concurrency mechanisms use dispatch, otherwise it doesn't.
For the static executable, it always adds them since that doesn't appear
to be very configurable.
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 demangling library can't use the error handling from the main runtime
because it isn't always linked with it. However, it's useful to have
some error handling, and in particular to be able to get data into the
crash logs.
This is complicated because of the way the demangling library gets used,
the upshot of which is that I've had to add a second object library just
for libswiftCore's use, so that the demangler will use the runtime's
error handling functions when present, and fall back on its own when
they aren't.
rdar://89139049
Creating a task for an async let will attempt to allocate the task in the async let's preallocated space, and if there's any space left over then it will use the extra for the new tasks's allocator. However, StackAllocator requires the preallocated buffer to be large enough to hold a slab header, but the task creation code doesn't check for that. As a result, the task creation code can end up passing a buffer that's too small to hold the slab header. When asserts are enabled, this is caught by an assert. When asserts are not enabled, disaster strikes. We end up computing a negative number for the remaining slab capacity, which underflows to a large positive number, causing the slab to overflow the async let's preallocated space. This results in weird memory corruption.
SR-15996
rdar://90357994