An AsyncFunctionPointer, defined in Task.h, is a struct consisting of
two i32s: (1) the relative address of the async function and (2) the
size of the async context to be allocated when calling that function.
Here, such structs are emitted for every async SILFunction that is
emitted.
When reemitting a type context descriptor, several fields
- method lookup function
- dispatch thunk
- nonoverride method descriptor
were previously being reemitted.
In a couple of earlier commits, that behavior was altered to delete the
fields before reemitting them.
3ad2777a68 [IRGen] Erase nonoverride descriptor on emission.
c25c180c08 [IRGen] Erase thunks before emission.
Here, the behavior is changed to simply exit early when these fields are
being reemitted. Also an assertion is added that these fields are
redefined only when reemitting the type context descriptor.
Previously, a call to emitMethodLookupFunction or emitDispatchThunk
would always simply emit a function, even if it had previously been
emitted. That was a problem since these emissions are triggered by
emitting class type context descriptors which can now be lazily
reemitted upon encountering prespecialized metadata.
Here, that behavior is changed to delete the old body, if any, before
emitting the body again.
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.
This became necessary after recent function type changes that keep
substituted generic function types abstract even after substitution to
correctly handle automatic opaque result type substitution.
Instead of performing the opaque result type substitution as part of
substituting the generic args the underlying type will now be reified as
part of looking at the parameter/return types which happens as part of
the function convention apis.
rdar://62560867
https://forums.swift.org/t/improving-the-representation-of-polymorphic-interfaces-in-sil-with-substituted-function-types/29711
This prepares SIL to be able to more accurately preserve the calling convention of
polymorphic generic interfaces by letting the type system represent "substituted function types".
We add a couple of fields to SILFunctionType to support this:
- A substitution map, accessed by `getSubstitutions()`, which maps the generic signature
of the function to its concrete implementation. This will allow, for instance, a protocol
witness for a requirement of type `<Self: P> (Self, ...) -> ...` for a concrete conforming
type `Foo` to express its type as `<Self: P> (Self, ...) -> ... for <Foo>`, preserving the relation
to the protocol interface without relying on the pile of hacks that is the `witness_method`
protocol.
- A bool for whether the generic signature of the function is "implied" by the substitutions.
If true, the generic signature isn't really part of the calling convention of the function.
This will allow closure types to distinguish a closure being passed to a generic function, like
`<T, U> in (*T, *U) -> T for <Int, String>`, from the concrete type `(*Int, *String) -> Int`,
which will make it easier for us to differentiate the representation of those as types, for
instance by giving them different pointer authentication discriminators to harden arm64e
code.
This patch is currently NFC, it just introduces the new APIs and takes a first pass at updating
code to use them. Much more work will need to be done once we start exercising these new
fields.
This does bifurcate some existing APIs:
- SILFunctionType now has two accessors to get its generic signature.
`getSubstGenericSignature` gets the generic signature that is used to apply its
substitution map, if any. `getInvocationGenericSignature` gets the generic signature
used to invoke the function at apply sites. These differ if the generic signature is
implied.
- SILParameterInfo and SILResultInfo values carry the unsubstituted types of the parameters
and results of the function. They now have two APIs to get that type. `getInterfaceType`
returns the unsubstituted type of the generic interface, and
`getArgumentType`/`getReturnValueType` produce the substituted type that is used at
apply sites.
Simplify calls to getAddrOfLLVMVariableOrGOTEquivalent() and
getAddrOfLLVMVariable() by moving the computation of the alignment and
default type into LinkEntity.
Co-authored-by: Joe Groff <jgroff@apple.com>
Abstract type/heap metadata access goes into MetadataRequest.
Metadata access starting from a heap object goes into GenHeap.
Accessing various components of class metadata goes into GenClass
or MetadataLayout.
We want to be able to re-order existing protocol requirements
and add new protocol requirements with default implementations.
Enable this by wrapping the witness table lookup inside a
thunk and calling the thunk, instead of open-coding the
witness table lookup directly in client code.