We had two notions of canonical types, one is the structural property
where it doesn't contain sugared types, the other one where it does
not contain reducible type parameters with respect to a generic
signature.
Rename the second one to a 'reduced type'.
This for some time has been crashing in IRGen in non-asserts builds and hitting
assertions in asserts builds. I think we were missing test coverage here and
that is why this basic-ish thing has been broken.
Basically at a high level, the actual expected ABI here is that the NSError is
marked non-nullable which is different from the expected ABI.
rdar://92755102
when two objc async functions are composed with each other,
i.e., f(g()), then the clean-ups for g() would get emitted
at an unexpected time, namely, during the suspension for
the call to f(). This means that using a clean-up to emit
the executor-hop breadcrumb was incorrect. The hop could
appear between a get_async continuation and its matching
await_continuation, which is an unsupported nested suspension.
This commit fixes that by removing the use of the breadcrumb
clean-up in favor of providing that breadcrumb directly to
the result plan, so that it may be emitted later on when the
result plan sees fit.
Fixes rdar://91502776
- Add a `[reflection]` bit to `alloc_box` instructions, to indicate that a box
should be allocated with reflection metadata attached.
- Add a `@captures_generics` attribute to SILLayouts, to indicate a type layout
that captures the generic arguments it's substituted with, meaning it can
recreate the generic environment without additional ABI-level arguments, like
a generic partial application can.
Previously, the AbstractionPattern that was used for the value
"returned" (i.e. via a completion handler) from ObjC mostly (but not
quite always) was "type".
The generated completion handler correctly (because this is required in
order to call _resumeUnsafeContinuation) reabstracted the block (e.g.
from @convention(block) to @substituted <T> () -> @out T for <()>). The
callee of the ObjC function, however, loaded the function from the block
as if it were not reabstracted (e.g. () -> ()).
On most platforms, that happened to work. On arm64e, that difference in
types caused in a difference in pointer signing, resulting in a failure
at runtime.
rdar://85526879
rdar://85526916
Clients can explicitly ask for the opened existential type on the archetype's generic environment,
or use `getExistentialType` to obtain a specific archetype's upper bounds.
Because AllocBoxToStack is not able to transform every alloc_box into an
alloc_stack, it's necessary to add begin_borrow [lexical] to every
alloc_box in order to provide lexical scopes for those alloc_boxes which
will not be transformed into alloc_stacks.
Use APIs for creating terminator results that handle forwarding
ownership consistently.
Add ManagedValue::forForwardedRValue(SILValue) to handle cleanups
consistently based on ownership forwarding.
Add SILGenBuilder::createForwardedTermResult(SILType type) for
creating termator results with the correct ownership and cleanups.
Add SILGenBuilder::createTermResult(SILType type, ValueOwnershipKind
ownership) that handles cleanup based on terminator result ownership.
Add SILGenBuilder::createOptionalSomeResult(SwitchEnumInst) so a lot
of code doesn't need to deal with unwrapping Optional types,
terminator results, and ownership rules.
Replace the existing "phi" APIs with a single
SILGenBuilder::createPhi(SILType, ValueOwnershipKind) that handles
cleanup based on phi ownership.
Phis and terminator results are fundamentally different and need to be handled differently everywhere. Remove the confusion where terminator results were generated with a "phi argument" API.
Previously, SILGen assumed that a foreign function could either have a
foreign async convention or a foreign error convention, but if it had
both, the error would be subsumed into the completion. That resulted in
failures to emit code for async calls of functions like
```
- (BOOL)minimalWithError:(NSError* _Nullable*)error
completionHandler:(void (^ _Nonnull)(void))completionHandler;
```
Here, SILGen gains the ability to emit such functions. To enable that,
a few changes were required when both conventions are present:
- a separate argument for each convention is used
- the ResultPlan is a ForeignErrorResultPlan nesting a
ForeignAsyncResultPlan
- the continuation is always of the form UnsafeContinuation<_, Error>
regardless of whether the completion handler takes an error
- the foreign error block fills the continuation with the error that was
passed by reference out of the ObjC method call
- the foreign error block branches to the block containing the await
instruction
rdar://80704984
Previously, AbstractionPattern::getOpaque() was used for async
continuations. That was problematic for functions like
```objc
- (void)performVoid2VoidWithCompletion:(void (^ _Nonnull)(void (^ _Nonnull)(void)))completion;
```
whose completion takes a closure. Doing so resulted in attempting to
build a block to func thunk where one of the functions had an out
parameter.
Instead, use the AbstractionPattern(ty).
rdar://79383990
Address a FIXME where lowered types rather than formal types were used
when converting from objc to native types which resulted in a failure to
convert block types.
This is kind of complicated, because an enum can be trivial for one case and not trivial for another case. We need to check at which parts of the function we can prove that the enum does (or could) have a trivial case. In such a branch, it's not required in SIL to destroy the enum location.
Also, document the rules and requirements for enum memory locations in SIL.rst.
rdar://73770085
Plumb generic signatures through the codegen for invoking foreign APIs as async, so that we
correctly handle APIs declared on ObjC lightweight generic classes. rdar://74361267
The goal of doing this is to reduce the amount of boilerplate and repeated code w.r.t. Continuation. Having just added `resume()` in four places, I got the sense that there was a lot of common code that was being duplicated. I removed the Throwing variants of these types (they can be expressed as Continuation<T, E:Error> instead of ThrowingContinuation<E>) and I broke out a significant amount of common code between CheckedContinuation and UnsafeContinuation into an implementation-only protocol to avoid repeating it. D.R.Y.
This change resolves rdar://74154769.
Immediately before invoking the ObjC API, get the current continuation, capture it into a block to
pass as the completion handler, and then await the continuation, whose resume/error successors
serve as the semantic return/throw result of the call. This should complete the caller-side part
of SILGen; the completion handler block implementation is however still only a stub.
Allow SILGen to not crash when invoking foreign async methods by emitting
`undef` for the completion callback going into the call, and for the
results that would be channeled back through awaiting the continuation.
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
This fixes an immediate bug with subst-to-orig conversion of
parameter functions that I'm surprised isn't otherwise tested.
More importantly, it preserves valuable information that should
let us handle a much wider variety of variant representations
that aren't necessarily expressed in the AbstractionPattern.
Motivation: `GenericSignatureImpl::getCanonicalSignature` crashes for
`GenericSignature` with underlying `nullptr`. This led to verbose workarounds
when computing `CanGenericSignature` from `GenericSignature`.
Solution: `GenericSignature::getCanonicalSignature` is a wrapper around
`GenericSignatureImpl::getCanonicalSignature` that returns the canonical
signature, or `nullptr` if the underlying pointer is `nullptr`.
Rewrite all verbose workarounds using `GenericSignature::getCanonicalSignature`.
By convention, most structs and classes in the Swift compiler include a `dump()` method which prints debugging information. This method is meant to be called only from the debugger, but this means they’re often unused and may be eliminated from optimized binaries. On the other hand, some parts of the compiler call `dump()` methods directly despite them being intended as a pure debugging aid. clang supports attributes which can be used to avoid these problems, but they’re used very inconsistently across the compiler.
This commit adds `SWIFT_DEBUG_DUMP` and `SWIFT_DEBUG_DUMPER(<name>(<params>))` macros to declare `dump()` methods with the appropriate set of attributes and adopts this macro throughout the frontend. It does not pervasively adopt this macro in SILGen, SILOptimizer, or IRGen; these components use `dump()` methods in a different way where they’re frequently called from debugging code. Nor does it adopt it in runtime components like swiftRuntime and swiftReflection, because I’m a bit worried about size.
Despite the large number of files and lines affected, this change is NFC.
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.
This is NFC for now, but I plan to build on this to (1) immediately
remove some unnecessary materialization and loads of the base value
and (2) to allow clients to load a borrowed value.
Delay allocating the result buffer for an opened Self return until right before it's needed. When a mutating method is invoked on an existential, the Self type won't be opened until late, when the formal access to the mutable value begins. Fixes rdar://problem/43507711.
This is in prepatation for splitting getAtUncurryLevel into one function that
returns the CalleeTypeInfo (which is needed early) and a later one that returns
a ManagedValue, which can occur later.
rdar://33358110
ground work for the syntactic bridging peephole.
- Pass source and dest formal types to the bridging routines in addition
to the dest lowered type. The dest lowered type is still necessary
in order to handle non-standard abstraction patterns for the dest type.
- Change bridging abstraction patterns to store bridged formal types
instead of the formal type.
- Improve how SIL type lowering deals with import-as-member patterns.
- Fix some AST bugs where inadequate information was being stored in
various expressions.
- Introduce the idea of a converting SGFContext and use it to regularize
the existing id-as-Any conversion peephole.
- Improve various places in SILGen to emit directly into contexts.