Commit Graph

58 Commits

Author SHA1 Message Date
Arnold Schwaighofer
1f890dc6a2 IRGen: Fix async dynamic replacements
We need to emit a full async suspend sequence when calling the
replacement.

rdar://77072724
2021-04-23 09:03:51 -07:00
Arnold Schwaighofer
cf55973973 Remove unused ResumeParentExecutor 2021-03-18 09:05:45 -07:00
Arnold Schwaighofer
249b27672a Remove unused error result storage from AsyncContext 2021-03-18 08:59:11 -07:00
Slava Pestov
c4c91e2393 Merge pull request #36482 from slavapestov/gencall-unused-var
IRGen: Remove unused variable
2021-03-18 10:20:34 -04:00
Slava Pestov
6d7714a57d IRGen: Remove unused variable 2021-03-18 00:10:56 -04:00
Arnold Schwaighofer
3bdd5cb99a IRGen: async error ABI
Throwing functions pass the error result in `swiftself` to the resume
partial function.
Therefore, `() async -> ()` to `() async throws -> ()` is not ABI compatible.

TODO: go through remaining failing IRGen async tests and replace the
illegal convert_functions.
2021-03-17 17:17:12 -07:00
Arnold Schwaighofer
f75fbb7594 IRGen: Async ABI passing parameter and results directly
The error is still passed in the async context. I will fix this in a
follow-up.
2021-03-17 07:41:01 -07:00
John McCall
6c879d6fd3 Change the async ABI to not pass the active task and executor.
Most of the async runtime functions have been changed to not
expect the task and executor to be passed in.  When knowing the
task and executor is necessary, there are runtime functions
available to recover them.

The biggest change I had to make to a runtime function signature
was to swift_task_switch, which has been altered to expect to be
passed the context and resumption function instead of requiring
the caller to park the task.  This has the pleasant consequence
of allowing the implementation to very quickly turn around when
it recognizes that the current executor is satisfactory.  It does
mean that on arm64e we have to sign the continuation function
pointer as an argument and then potentially resign it when
assigning into the task's resume slot.

rdar://70546948
2021-03-16 22:52:54 -04:00
Konrad `ktoso` Malawski
6f4fca8721 Merge branch 'main' into wip-no-escape-group 2021-02-24 08:59:53 +09:00
John McCall
2012195cd5 Alter the runtime interface for awaiting futures and task groups.
First, just call an async -> T function instead of forcing the caller
to piece together which case we're in and perform its own copy.  This
ensures that the task is actually kept alive properly.

Second, now that we no longer implicitly depend on the waiting tasks
being run synchronously, go ahead and schedule them to run on the
global executor.

This solves some problems which were blocking the work on TLS-ifying
the task/executor state.
2021-02-21 23:48:13 -05:00
Konrad `ktoso` Malawski
a226259d84 [Concurrency] TaskGroup moves out of AsyncTask, non escaping body 2021-02-22 13:26:27 +09:00
Arnold Schwaighofer
4373bdd6d0 Conditionally start using llvm::CallingConv::SwiftTail for async functions
This is conditional on UseAsyncLowering and in the future should also be
conditional on `clangTargetInfo.isSwiftAsyncCCSupported()` once that
support is merged.

Update tests to work either with swiftcc or swifttailcc.
2021-02-18 09:25:15 -08:00
nate-chandler
de63a23e77 Merge pull request #35603 from nate-chandler/concurrency/irgen/rdar71378532
[Async CC] Make error indirect.
2021-02-16 07:39:14 -08:00
Slava Pestov
72e1f02ae2 IRGen: Fix async dispatch thunk emission with loadable return value
Fixes <rdar://problem/74246091>.
2021-02-12 14:06:07 -05:00
Nate Chandler
e2a8abc9e5 [Async CC] Make error indirect.
Previously, the error stored in the async context was of type SwiftError
*.  In order to enable the context to be callee released, make it
indirect and change its type to SwiftError **.

rdar://71378532
2021-02-11 11:34:47 -08:00
swift-ci
89c8005a80 Merge remote-tracking branch 'origin/main' into rebranch 2021-01-27 15:52:25 -08:00
Slava Pestov
c79de40225 IRGen: Emit async function pointers for resilient class and protocol dispatch thunks
This adds new kinds of link entities corresponding to the three
dispatch thunk link entity kinds:

- DispatchThunkAsyncFunctionPointer
- DispatchThunkInitializerAsyncFunctionPointer
- DispatchThunkAllocatorAsyncFunctionPointer
2021-01-27 15:21:22 -05:00
Arnold Schwaighofer
25ff64686d Adjust to llvm's byVal parameter attributes needing the storage type
rdar://73172496
2021-01-14 15:33:42 -08:00
Richard Wei
de2dbe57ed [AutoDiff] Bump-pointer allocate pullback structs in loops. (#34886)
In derivatives of loops, no longer allocate boxes for indirect case payloads. Instead, use a custom pullback context in the runtime which contains a bump-pointer allocator.

When a function contains a differentiated loop, the closure context is a `Builtin.NativeObject`, which contains a `swift::AutoDiffLinearMapContext` and a tail-allocated top-level linear map struct (which represents the linear map struct that was previously directly partial-applied into the pullback). In branching trace enums, the payloads of previously indirect cases will be allocated by `swift::AutoDiffLinearMapContext::allocate` and stored as a `Builtin.RawPointer`.
2020-11-30 15:49:38 -08:00
Arnold Schwaighofer
fbfcaabb83 IRGen: Allow calling a pre-defined async silgen_name function using the async convention
The function can then be implemented in the runtime.

Note: This is a temporary hack.
2020-11-17 15:02:13 -08:00
nate-chandler
f8556287c7 Merge pull request #34765 from nate-chandler/concurrency/irgen/thick-context-in-async-context
[Async CC] Move thick context into async context.
2020-11-16 14:21:46 -08:00
Nate Chandler
eba057fe88 [Async CC] Move thick context into async context.
Previously, the thick context was passed as a fourth parameter to
partial apply forwarders.  Here, the thick context is instead moved into
the async context at the local context position.  To support this, the
local context is made always available.
2020-11-16 12:02:32 -08:00
Doug Gregor
069dfad638 [Concurrency] Add Builtin.createAsyncTaskFuture.
This new builtin allows the creation of a "future" task, which calls
down to swift_task_create_future to actually form the task.
2020-11-15 22:37:13 -08:00
Arnold Schwaighofer
2271d4df55 Use taskAlloc for dynamic allocas
Async coroutines don't support dynamic allocas.
2020-11-13 10:41:42 -08:00
Arnold Schwaighofer
74419d0885 Lower asynchronous functions to LLVM async coroutine intrinsics
rdar://70097093
2020-11-13 10:41:42 -08:00
Nate Chandler
2d21932672 [Async CC] Add constant "pointer" for async func.
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.
2020-11-12 18:20:10 -08:00
Doug Gregor
4c2c2f32e9 [Concurrency] Implement a builtin createAsyncTask() to create a new task.
`Builtin.createAsyncTask` takes flags, an optional parent task, and an
async/throwing function to execute, and passes it along to the
`swift_task_create_f` entry point to create a new (potentially child)
task, returning the new task and its initial context.
2020-11-07 23:05:04 -08:00
Doug Gregor
a2d7c701a4 Merge pull request #34600 from DougGregor/async-task-builtins
[Concurrency] Add cancelAsyncTask() builtin.
2020-11-05 20:53:25 -08:00
Doug Gregor
c291eb596b [Concurrency] Add cancelAsyncTask() builtin.
Implement a new builtin, `cancelAsyncTask()`, to cancel the given
asynchronous task. This lowers down to a call into the runtime
operation `swift_task_cancel()`.

Use this builtin to implement Task.Handle.cancel().
2020-11-05 13:50:17 -08:00
Nate Chandler
8e2b1277cc [NFC] Clang-formatted 8e9dec23fc.
The commit with the following message wasn't previously formatted.  That
oversight is fixed here.

    [NFC] Construct AsyncContextLayout from module.

    Previously, an IRGenFunction was being passed to the functions that
    construct an AsyncContextLayout.  That was not actually necessary and
    prevented construction of the layout in contexts where no IRGenFunction
    was present.  Here that requirement is eased to requiring an IRGenModule
    which is indeed required to construct an AsyncContextLayout.
2020-11-05 13:37:23 -08:00
Nate Chandler
8e9dec23fc [NFC] Construct AsyncContextLayout from module.
Previously, an IRGenFunction was being passed to the functions that
construct an AsyncContextLayout.  That was not actually necessary and
prevented construction of the layout in contexts where no IRGenFunction
was present.  Here that requirement is eased to requiring an IRGenModule
which is indeed required to construct an AsyncContextLayout.
2020-11-04 18:42:06 -08:00
Nate Chandler
80d1f83b6d [Async CC] Add coroutine fields to context.
The following fields are now available when the function is a coroutine:
- TaskContinuationFunction * __ptrauth(...) yieldToCaller?
- TaskContinuationFunction * __ptrauth(...) resumeFromYield?
- TaskContinuationFunction * __ptrauth(...) abortFromYield?
- ExecutorRef calleeActorDuringYield?
- YieldTypes yieldValues...

These fields have yet to be filled in.

The following field are now available when the function is NOT a
coroutine (whereas previously they were always available):
- ResultTypes directResults...
2020-10-27 18:11:58 -07:00
Nate Chandler
c22c0c523a [Async CC] Add Flags to context. 2020-10-27 18:07:50 -07:00
Nate Chandler
59a309c2ef [NFC] Matched decl arg nams to defn arg names. 2020-10-27 18:06:53 -07:00
Nate Chandler
1e0d6f39d7 [Async CC] Add ResumeParentExecutor to context. 2020-10-27 12:40:42 -07:00
Nate Chandler
f29f43907f [Async CC] Add ResumeParent to async context. 2020-10-27 12:40:40 -07:00
Nate Chandler
5d67c4a74b [Async CC] Add parent to async context. 2020-10-27 12:39:56 -07:00
Nate Chandler
b65d71b24a [Async CC] Added conveniences to retrieve argumments.
Because all async functions have the same signature, namely

  void(%swift.task*, %swift.executor*, %swift.context*)

it is always possible to provide access to the three argument values
(the current task, current executor, and current context) within an
IRGenFunction which is async.  Here, that is provided in the form of
IRGenFunction::getAsyncExecutor,IRGenFunction::getAsyncContext, and
IRGenFunction::getAsyncTask.
2020-10-26 20:07:56 -07:00
Nate Chandler
506473dfba [Async CC] Supported partial application.
The majority of support comes in the form of emitting partial
application forwarders for partial applications of async functions.
Such a partial application forwarder must take an async context which
has been partially populated at the apply site.  It is responsible for
populating it "the rest of the way".  To do so, like sync partial
application forwarders, it takes a second argument, its context, from
which it pulls the additional arguments which were capture at
partial_apply time.

The size of the async context that is passed to the forwarder, however,
can't be known at the apply site by simply looking at the signature of
the function to be applied (not even by looking at the size associated
with the function in the special async function pointer constant which
will soon be emitted).  The reason is that there are an unknown (at the
apply site) number of additional arguments which will be filled by the
partial apply forwarder (and in the case of repeated partial
applications, further filled in incrementally at each level).  To enable
this, there will always be a heap object for thick async functions.
These heap objects will always store the size of the async context to be
allocated as their first element.  (Note that it may be possible to
apply the same optimization that was applied for thick sync functions
where a single refcounted object could be used as the context; doing so,
however, must be made to interact properly with the async context size
stored in the heap object.)

To continue to allow promoting thin async functions to thick async
functions without incurring a thunk, at the apply site, a null-check
will be performed on the context pointer.  If it is null, then the async
context size will be determined based on the signature.  (When async
function pointers become pointers to a constant with a size i32 and a
relative address to the underlying function, the size will be read from
that constant.)  When it is not-null, the size will be pulled from the
first field of the context (which will in that case be cast to
<{%swift.refcounted, i32}>).

To facilitate sharing code and preserving the original structure of
emitPartialApplicationForwarder (which weighed in at roughly 700 lines
prior to this change), a new small class hierarchy, descending from
PartialApplicationForwarderEmission has been added, with subclasses for
the sync and async case.  The shuffling of arguments into and out of the
final explosion that was being performed in the synchronous case has
been preserved there, though the arguments are added and removed through
a number of methods on the superclass with more descriptive names.  That
was necessary to enable the async class to handle these different
flavors of parameters correctly.

To get some initial test coverage, the preexisting
IRGen/partial_apply.sil and IRGen/partial_apply_forwarder.sil tests have
been duplicated into the async folder.  Those tests cases within these
files which happened to have been crashing have each been extracted into
its own runnable test that both verifies that the compiler does not
crash and also that the partial application forwarder behaves correctly.
The FileChecks in these tests are extremely minimal, providing only
enough information to be sure that arguments are in fact squeezed into
an async context.
2020-10-22 12:21:56 -07:00
Nate Chandler
03f4e40f20 [Async CC] Move self after formal arguments.
Partial applies of methods supply only self.  When applies of the
resulting thick function are performed, that self was one of the
arguments is not known.  As a result, self must appear after the fields
that might be supplied at the apply site, which  is to say all the
arguments.
2020-10-21 16:20:51 -07:00
Nate Chandler
a9aee1b9dd [Async CC] Put bindings after formal arguments.
Bindings will always be supplied by the first partial apply, so they
will only be added to the async context when its full layout is known.
If they are earlier in the layout, subsequent partial applies will put
their arguments into the wrong position because they will not be privy
to the space requirements of the bindings.
2020-10-21 16:18:29 -07:00
Nate Chandler
97202faee5 [Async CC] Put direct returns after indirect returns.
For callers who do not know the actual type of the called function, e.g.
when the called function is the result of a partial apply, the offset to
the direct returns would otherwise not be known.
2020-10-21 16:18:25 -07:00
Nate Chandler
7d74a8614d [Concurrency] Async CC supports witness methods.
Previously, the AsyncContextLayout did not make space for the trailing
witness fields (self metadata and self witness table) and the
AsyncNativeCCEntryPointArgumentEmission could consequently not vend
these fields.  Here, the fields are added to the layout.
2020-10-06 17:03:03 -07:00
Nate Chandler
b90cab6f1b [NFC] Made indexing on AsyncContextLayout private.
Previously the methods for getting the index into the layout were public
and were being used to directly access the underlying buffer.  Here,
that abstraction leakage is fixed and field access is forced to go
through the appropriate methods.
2020-10-06 11:58:27 -07:00
Nate Chandler
d2fc2c1e35 [IRGen] Silenced unused variable warning. 2020-10-06 11:54:38 -07:00
Nate Chandler
ee88152d6b [Concurrency] First steps towards async CC.
Here, the following is implemented:
- Construction of SwiftContext struct with the fields needed for calling
  functions.
- Allocating and deallocating these swift context via runtime calls
  before calling async functions and after returning from them.
- Storing arguments (including bindings and the self parameter but not
  including protocol fields for witness methods) and returns (both
  direct and indirect).
- Calling async functions.

Additional things that still need to be done:
- protocol extension methods
- protocol witness methods
- storing yields
- partial applies
2020-10-05 20:43:51 -07:00
Joe Groff
03c7919b4a SIL: Add fields to SILFunctionType for substituted function types.
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.
2019-10-25 13:38:51 -07:00
Arnold Schwaighofer
882059674f IRGen: Support for trivial @noescape function types
- make @noescape function types trivial
- think_to_thick_function with @noescape result type
- Fix for getSwiftFunctionPointerCallee

Part of:
SR-5441
rdar://36116691
2018-02-13 04:19:59 -08:00
John McCall
3c54c0edfc IRGen and basic optimizer support for coroutines. 2018-01-09 11:35:09 -05:00
Joe Shajrawi
62d823c56d Code size: Do not use a global state for isOutlined 2017-11-15 15:28:27 -08:00